Değişken bellek adresini hızlı bir şekilde yazdırma


166

[NSString stringWithFormat:@"%p", myVar]Objective-C'den yeni Swift dilinde simüle etmek için yine de var mı ?

Örneğin:

let str = "A String"
println(" str value \(str) has address: ?")

2
In [NSString stringWithFormat:@"%p", myVar], myVarbir işaretçi olmalıdır. Swift kodunuzda, strbir işaretçi değildir. Dolayısıyla karşılaştırma geçerli değildir.
user102008

5
En azından bunu yazarken, yukarıdaki iki yorumun yanlış olduğunu belirtmek gerekir.
Ben Leggiero

Yanıtlar:


112

Hızlı 2

Bu artık standart kütüphanenin parçasıdır: unsafeAddressOf.

/// Return an UnsafePointer to the storage used for `object`.  There's
/// not much you can do with this other than use it to identify the
/// object

Hızlı 3

Swift 3 için withUnsafePointerşunları kullanın :

var str = "A String"
withUnsafePointer(to: &str) {
    print(" str value \(str) has address: \($0)")
}

2
unsafeAddressOf () yalnızca sınıf türleri için çalışır (aşağıdaki @Nick işaret ettiği gibi). Bu nedenle, bu yanıt yalnızca Foundation içe aktarılırsa ve String NSString ile köprülenirse çalışır. Düz Swift'te String bir değer türüdür ve unsafeAddressOf adresini almak için kullanılamaz (deneme derleme hatasıyla sonuçlanır).
Stephen Schaub

29
Swift 3 ile değişmez değerin adresini yazdırmak istersem ne olur ? hata ile withUnsafePointersonuçlanır cannot pass immutable value as inout argument.
Alexander Vasenin

12
Kabul edilmiş ve en yüksek oyu almış olmasına rağmen, yine de yanlış sonuçlar veriyor . Örnek: print(self.description)baskılar <MyViewController: 0x101c1d580>, referans olarak kullanıyoruz. açıkça farklı bir adres olan var mutableSelf = self; withUnsafePointer(to: &mutableSelf) { print(String(format: "%p", $0)) }baskılar 0x16fde4028. Nedenini açıklayan var mı?
Alexander Vasenin

4
BTW, bu 0x101c1d580beklendiği gibi yazdırılıyor :print(String(format: "%p", unsafeBitCast(self, to: Int.self)))
Alexander Vasenin

8
@nyg Cevabınız bana asıl hata nedeni için bir ipucu verdi: bir yapıdır UnsafePointer, bu yüzden işaret ettiği adresi yazdırmak için (yapının kendisini değil) yazdırmanız gerekir String(format: "%p", $0.pointee)!
Alexander Vasenin

214

Not: Bu referans türleri içindir.

Hızlı 4/5:

print(Unmanaged.passUnretained(someVar).toOpaque())

SomeVar'ın bellek adresini yazdırır. (@Ying sayesinde)


Hızlı 3.1:

print(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())

SomeVar'ın bellek adresini yazdırır.



2
Xcode 8.2.1 otomatik düzeltme bana şimdi olduğunu söylüyorprint(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
Jeff

2
Bu, sadece someVar bir nesne olduğunda geçerli olmaz. SomeVar, struct gibi bir değer türü olursa, bu her yürütüldüğünde farklı bir adres verir.
OutOnAWeekend

3
@OutOnAWeekend Haklısınız, büyük olasılıkla yapı bağımsız değişken olarak iletildiğinde kopyalanıyor. Kullanılması Unmanagedböyle yapılabilir: print(Unmanaged<AnyObject>.fromOpaque(&myStruct).toOpaque()).
nyg

1
Swift 4'ten itibaren, bu büyüyü de basabildim - Unmanaged.passUnretained(someVar).toOpaque()(jenerik spesifikasyona gerek yok)
Ying

2
Swift 4 yanıtı mükemmel. Ayrıca dize temsilini yazdırmadan almak istiyorsanız debugDescription, sonuna eklemenizi öneririm .
Patrick

51

Bu cevabın oldukça eski olduğuna dikkat edin. Açıkladığı yöntemlerin çoğu artık çalışmıyor. Özel .coreolarak artık erişilemiyor.

Ancak @ drew'un cevabı doğru ve basittir:

Bu artık standart kütüphanenin bir parçası: unsafeAddressOf.

Yani sorularınızın cevabı:

println(" str value \(str) has address: \(unsafeAddressOf(str))")

Doğru olarak işaretlenmiş orijinal cevap (gelecek nesiller / nezaket için):

Swift işaretçileri "gizler", ancak yine de kaputun altında bulunurlar. (çünkü çalışma zamanının buna ihtiyacı olduğu ve Objc ve C ile uyumluluk nedeniyle)

Ancak bilmeniz gereken birkaç şey var, ancak önce bir Swift String'in bellek adresini nasıl yazdırabilirim?

    var aString : String = "THIS IS A STRING"
    NSLog("%p", aString.core._baseAddress)  // _baseAddress is a COpaquePointer
   // example printed address 0x100006db0

Bu, dizenin bellek adresini yazdırır, XCode -> Debug Workflow -> Belleği Görüntüle'yi açar ve yazdırılan adrese giderseniz, dizenin ham verilerini görürsünüz. Bu bir dize değişmez değeri olduğundan, bu ikili (depo veya yığın değil) depolama içindeki bir bellek adresidir.

Ancak, eğer

    var aString : String = "THIS IS A STRING" + "This is another String"
    NSLog("%p", aString.core._baseAddress)

    // example printed address 0x103f30020

Dize çalışma zamanında oluşturulduğundan, bu yığın üzerinde olacaktır

NOT: .core._baseAddress belgelenmemiştir, değişken denetçiye bakarak buldum ve gelecekte gizli olabilir

_baseAddress tüm türlerde mevcut değildir, burada CInt ile başka bir örnek

    var testNumber : CInt = 289
    takesInt(&testNumber)

takesIntBöyle bir C yardımcı işlevi nerede

void takesInt(int *intptr)
{
    printf("%p", intptr);
}

Swift tarafında, bu işlev, bu takesInt(intptr: CMutablePointer<CInt>)nedenle bir CMutablePointer bir CInt alır ve & varname ile elde edebilirsiniz

İşlev yazdırılır 0x7fff5fbfed98 , bu hafıza adresinde 289 bulacaksınız (onaltılık gösterimde). İçeriğini şununla değiştirebilirsiniz:*intptr = 123456

Şimdi, bilinmesi gereken başka şeyler var.

Dize, hızlı bir şekilde, bir nesne değil, ilkel bir türdür.
CInt, C int Tipine eşlenmiş bir Swift türüdür.
Bir nesnenin bellek adresini istiyorsanız, farklı bir şey yapmanız gerekir.
Swift, C ile etkileşime girerken kullanılabilecek bazı İşaretçi Türlerine sahiptir ve bunları burada okuyabilirsiniz: Swift İşaretçi Türleri
Ayrıca, nasıl dönüştürüleceğini anlamak için bildirimlerini (cmd + türünü tıklatma) keşfetme hakkında daha fazla bilgi edinebilirsiniz. diğerine bir tür işaretçi

    var aString : NSString = "This is a string"  // create an NSString
    var anUnmanaged = Unmanaged<NSString>.passUnretained(aString)   // take an unmanaged pointer
    var opaque : COpaquePointer = anUnmanaged.toOpaque()   // convert it to a COpaquePointer
    var mut : CMutablePointer = &opaque   // this is a CMutablePointer<COpaquePointer>

    printptr(mut)   // pass the pointer to an helper function written in C

printptr bu uygulamayla oluşturduğum bir C yardımcı işlevidir

void printptr(void ** ptr)
{
    printf("%p", *ptr);
}

Yine, yazdırılan adrese bir örnek: 0x6000000530b0ve bellek denetçisinden geçerseniz NSString'inizi bulacaksınız

Swift'teki işaretçilerle yapabileceğiniz bir şey (bu, giriş parametreleriyle bile yapılabilir)

    func playWithPointer (stringa :AutoreleasingUnsafePointer<NSString>) 
    {
        stringa.memory = "String Updated";
    }

    var testString : NSString = "test string"
    println(testString)
    playWithPointer(&testString)
    println(testString)

Veya Objc / c ile etkileşim

// objc side
+ (void)writeString:(void **)var
{
    NSMutableString *aString = [[NSMutableString alloc] initWithFormat:@"pippo %@", @"pluto"];
    *var = (void *)CFBridgingRetain(aString);   // Retain!
}

// swift side
var opaque = COpaquePointer.null()   // create a new opaque pointer pointing to null
TestClass.writeString(&opaque)
var string = Unmanaged<NSString>.fromOpaque(opaque).takeRetainedValue()
println(string)
// this prints pippo pluto

evet, işaretçinin çıkması gerekir, ancak bahsettiğiniz uyumluluk nedeniyle değil. genellikle işletim sistemi tarafından kullanılan işaretçiler. dil üst düzey dil olsa bile, işaretçiler işletim sisteminin motorunda herhangi bir zamanda herhangi bir dilde mevcut olmalıdır.
holex

Dedim "uyumluluk nedeniyle VE çünkü çalışma zamanı ihtiyacı" :-) ikinci ifade söylediklerinizi yeniden
özetliyor

Bunun artık geçerli olmadığını varsayıyorum?
aleclarson

Evet. @Drew'dan doğru cevabı düzenledim.
Rog

@LombaX biz sadece referans tipi adresi yazdırabilirsiniz? Değişkenlerin adreslerini yazdıramıyorum?
AbhimanyuAryan

21

Bir nesnenin (yığın) adresini almak için

func address<T: AnyObject>(o: T) -> Int {
    return unsafeBitCast(o, Int.self)
}

class Test {}
var o = Test()
println(NSString(format: "%p", address(o))) // -> 0x7fd5c8700970

( Düzenle: Swift 1.2 artık benzer bir işlev içeriyor unsafeAddressOf.)

Objective-C'de bu olurdu [NSString stringWithFormat:@"%p", o].

oörneğe bir referanstır. Dolayısıyla o, başka bir değişkene atanmışsa o2, için döndürülen adres o2aynı olacaktır.

Bu, yapılar (dahil String) ve ilkel türler (gibi Int) için geçerli değildir, çünkü bunlar doğrudan yığın üzerinde yaşar. Ancak yığındaki yeri alabiliriz.

Bir yapının (yığın) adresini almak için yerleşik tür veya nesne başvurusu

func address(o: UnsafePointer<Void>) -> Int {
    return unsafeBitCast(o, Int.self)
}

println(NSString(format: "%p", address(&o))) // -> 0x10de02ce0

var s = "A String"
println(NSString(format: "%p", address(&s))) // -> 0x10de02ce8

var i = 55
println(NSString(format: "%p", address(&i))) // -> 0x10de02d00

Objective-C'de bu [NSString stringWithFormat:@"%p", &o]veya olur [NSString stringWithFormat:@"%p", &i].

syapıdır. Bu nedenle s, başka bir değişkene atanırsa s2, değer kopyalanır ve döndürülen adres s2farklı olur.

Birbirine nasıl uyar (işaretçi özeti)

Objective-C gibi, ile ilişkili iki farklı adres vardır o. Birincisi, nesnenin konumudur, ikincisi, nesneye yapılan referansın (veya işaretçinin) konumudur.

Evet, bu, 0x7fff5fbfe658 adresinin içeriğinin, hata ayıklayıcının bize söyleyebileceği gibi 0x6100000011d0 sayısı olduğu anlamına gelir:

(lldb) x/g 0x7fff5fbfe658
0x7fff5fbfe658: 0x00006100000011d0

Yani, dizeler yapı olmak dışında, dahili olarak bunların hepsi (Objective-) C ile aynı şekilde çalışır.

(Xcode 6.3 itibariyle geçerlidir)


Hmm. Bir nesnenin özelliğinin yığın adresini almak tutarlı değildir. Herhangi bir fikir? Bu özü inceleyin!
aleclarson

Nesnenin özellikleri yığın üzerinde değil, yığın üzerindedir. Bir sınıf örneğinin özelliğini UnsafePointer olarak ilettiğinizde, Swift ilk önce değeri kopyalar ve kopyanın adresini alırsınız. Bunun, C kodunun nesnenin arayüzünü atlamasını ve tutarsız bir duruma neden olmasını önlemek olduğundan şüpheleniyorum. Bu konuda bir yol olup olmadığını bilmiyorum.
nschum


20

TL; DR

struct MemoryAddress<T>: CustomStringConvertible {

    let intValue: Int

    var description: String {
        let length = 2 + 2 * MemoryLayout<UnsafeRawPointer>.size
        return String(format: "%0\(length)p", intValue)
    }

    // for structures
    init(of structPointer: UnsafePointer<T>) {
        intValue = Int(bitPattern: structPointer)
    }
}

extension MemoryAddress where T: AnyObject {

    // for classes
    init(of classInstance: T) {
        intValue = unsafeBitCast(classInstance, to: Int.self)
        // or      Int(bitPattern: Unmanaged<T>.passUnretained(classInstance).toOpaque())
    }
}

/* Testing */

class MyClass { let foo = 42 }
var classInstance = MyClass()
let classInstanceAddress = MemoryAddress(of: classInstance) // and not &classInstance
print(String(format: "%018p", classInstanceAddress.intValue))
print(classInstanceAddress)

struct MyStruct { let foo = 1 } // using empty struct gives weird results (see comments)
var structInstance = MyStruct()
let structInstanceAddress = MemoryAddress(of: &structInstance)
print(String(format: "%018p", structInstanceAddress.intValue))
print(structInstanceAddress)

/* output
0x0000000101009b40
0x0000000101009b40
0x00000001005e3000
0x00000001005e3000
*/

( Gist )


Swift'te ya değer türleri (yapılar) ya da referans türleri (sınıflar) ile ilgileniyoruz. Yaparken:

let n = 42 // Int is a structure, i.e. value type

X adresinde bir miktar bellek ayrılır ve bu adreste 42 değerini buluruz. Bunu yapmak &nX adresini işaret eden bir işaretçi oluşturur, bu nedenle &nbize nerede bulunduğunu söyler n.

(lldb) frame variable -L n
0x00000001005e2e08: (Int) n = 42
(lldb) memory read -c 8 0x00000001005e2e08
0x1005e2e08: 2a 00 00 00 00 00 00 00 // 0x2a is 42

Yaparken:

class C { var foo = 42, bar = 84 }
var c = C()

Bellek iki yerde tahsis edilir:

  • sınıf örneği verilerinin bulunduğu Y adresinde ve
  • sınıf örneği başvurusunun bulunduğu X adresinde.

Söylendiği gibi, sınıflar referans türleridir: yani değeri cX adresinde bulunur, burada Y değerini buluruz. Ve Y + 16 adresinde bulacağızfoo adresinde ve Y + 24 adresinde buluruz bar( + 0 ve + 8'de tür verilerini ve referans sayılarını bulacağız, size bunun hakkında daha fazla bilgi veremem ...).

(lldb) frame variable c // gives us address Y
(testmem.C) c = 0x0000000101a08f90 (foo = 42, bar = 84)
(lldb) memory read 0x0000000101a08f90 // reading memory at address Y
0x101a08f90: e0 65 5b 00 01 00 00 00 02 00 00 00 00 00 00 00
0x101a08fa0: 2a 00 00 00 00 00 00 00 54 00 00 00 00 00 00 00

0x2a42 (foo) ve 0x5484 (bar) 'dır.

Her iki durumda da, &nveya &cadresini kullanmak bize X adresini verecektir. Değer türleri için istediğimiz budur, ancak referans türleri için değildir.

Yaparken:

let referencePointer = UnsafeMutablePointer<C>(&c)

Referans üzerinde bir işaretçi oluşturuyoruz, yani X adresini işaret eden bir işaretçi withUnsafePointer(&c) {}. Kullanırken aynı şey .

(lldb) frame variable referencePointer
(UnsafeMutablePointer<testmem.C>) referencePointer = 0x00000001005e2e00 // address X
(lldb) memory read -c 8 0x00000001005e2e00 // read memory at address X
0x1005e2e00: 20 ec 92 01 01 00 00 00 // contains address Y, consistent with result below:
(lldb) frame variable c
(testmem.C) c = 0x000000010192ec20 (foo = 42, bar = 84)

Artık kaputun altında neler olup bittiğini daha iyi anladığımıza ve şimdi X adresinde Y adresini (istediğimiz adres) bulacağımızı anlamak için aşağıdakileri yapabiliriz:

let addressY = unsafeBitCast(c, to: Int.self)

Doğrulanıyor:

(lldb) frame variable addressY -f hex
(Int) addressY = 0x0000000101b2fd20
(lldb) frame variable c
(testmem.C) c = 0x0000000101b2fd20 (foo = 42, bar = 84)

Bunu yapmanın başka yolları da var:

let addressY1 = Int(bitPattern: Unmanaged.passUnretained(c).toOpaque())
let addressY2 = withUnsafeMutableBytes(of: &c) { $0.load(as: Int.self) }

toOpaque()aslında çağırır unsafeBitCast(c, to: UnsafeMutableRawPointer.self).

Umarım bu yardımcı olmuştur ... benim için yaptı 😆.


Sadece aynı yapının adresini 2 farklı örnek üzerinden yazdırmaya çalışırken MemoryLocation2 farklı adres ürettiğini fark ettim .
user1046037

@ user1046037 Teşekkürler, sınıf init için değişiklik yaptı. Ayrıca iki farklı adres alıyorum, ancak yalnızca boş bir yapı kullandığımda. Boş yapı kullanmak her zaman bana garip sonuçlar verir. Benim tahminim derleyici bazı optimizasyonlar yapar ...
nyg

@ user1046037 Kontrol edin: pastebin.com/mpd3ujw2 . Görünüşe göre, tüm boş yapılar aynı bellek adresini işaret ediyor. Ancak, işaretçiyi bir değişkende saklamak istediğimizde, bir kopyası (ya da yapı?) Bir kopyasını oluşturacaktır ...
nyg

Bu ilginç, ancak iki kez basıldığında farklı bellek adreslerini yazdırıyor. Yukarıdaki cevaplar için de durum aynıdır.
user1046037

@ user1046037 Ne demek istediğini anladığımdan emin değilim, kodun var mı? (Ben her zaman aynı bellek adresini
alıyorum

15

Referans Türleri:

  • Bir referans türünün bellek adresini, kimliği temsil ettiği için almak mantıklıdır.
  • === kimlik operatörü, aynı referansı işaret eden 2 nesnenin kontrol edilmesi için kullanılır.
  • kullanım ObjectIdentifierBellek adresini almak için

Kod:

class C {}

let c1 = C()
let c2 = c1

//Option 1:
print("c1 address: \(Unmanaged.passUnretained(c1).toOpaque())") 

//Option 2:
let o1 = ObjectIdentifier(c1)
let o2 = ObjectIdentifier(c2)

print("o1 -> c1 = \(o1)")
print("o2 -> c2 = \(o2)")

if o1 == o2 {
    print("c1 = c2")
} else {
    print("c1 != c2")
}

//Output:
//c1 address: 0x000060c000005b10
//o1 -> c1 = ObjectIdentifier(0x000060c000005b10)
//o2 -> c2 = ObjectIdentifier(0x000060c000005b10)
//c1 = c2

Değer Türleri:

  • Bir değer türünün bellek adresini alma ihtiyacı (bir değer olduğu için) çok önemli değildir ve vurgu, değerin eşitliğine daha fazla olacaktır.

12

Sadece şunu kullanın:

print(String(format: "%p", object))

Derleyici şikayeti " MyClass?" ile CVarArg'a uymuyorsa, bunu yapabilirsiniz extension Optional : CVarArg { }. Aksi halde bu, diğer cevapların "güvensiz" deliliği olmadan adresleri yazdırıyor gibi görünüyor.
Devin Lane

var _cVarArgEncoding: [Int]Tarihinde uygulanmasını gerektirir CVarArg. Bunun nasıl uygulanması gerektiği net değil.
Yuchen Zhong

10

Bunu sadece hata ayıklayıcıda görmek ve onunla başka bir şey yapmak istemiyorsanız, Intişaretçiyi gerçekten almanıza gerek yoktur . Bir nesnenin adresinin dize halinde temsilini almak için, sadece şöyle bir şey kullanın:

public extension NSObject { // Extension syntax is cleaner for my use. If your needs stem outside NSObject, you may change the extension's target or place the logic in a global function
    public var pointerString: String {
        return String(format: "%p", self)
    }
}

Örnek kullanım:

print(self.pointerString, "Doing something...")
// Prints like: 0x7fd190d0f270 Doing something...

Ayrıca, bir nesneyi geçersiz kılmadan kolayca yazdırabileceğinizidescription ve daha açıklayıcı (genellikle şifreli ise) metnin yanında işaretçi adresini göstereceğini unutmayın.

print(self, "Doing something else...")
// Prints like: <MyModule.MyClass: 0x7fd190d0f270> Doing something else...
// Sometimes like: <_TtCC14__lldb_expr_668MyModule7MyClass: 0x7fd190d0f270> Doing something else...

1
Lütfen neden herhangi bir downvotes eşlik açıklayan bir yorum ile, bu yüzden ben ve buraya gelen herkes bunun neden kötü bir çözüm olduğunu
biliyorum

1
Basit ve temiz!
badhanganesh

9

Hızlı 5

extension String {
    static func pointer(_ object: AnyObject?) -> String {
        guard let object = object else { return "nil" }
        let opaque: UnsafeMutableRawPointer = Unmanaged.passUnretained(object).toOpaque()
        return String(describing: opaque)
    }
}

Kullanımı:

print("FileManager.default: \(String.pointer(FileManager.default))")
// FileManager.default: 0x00007fff5c287698

print("nil: \(String.pointer(nil))")
// nil: nil

Bu cevap yanlış. Aynı sınıftan iki örnek yaparsanız, her iki örnek için aynı bellek adresini döndürür. Unmanaged.passUnretained(myObject).toOpaque()yerine düzgün çalışıyor.
Padraig

@Padraig Teşekkürler, kodunuzla güncelledim. Ne yazık ki şimdi bir AnyObjectparametre alıyor. AnyGiriş türü olarak tercih ederim .
neoneye

6

Swift4'te Dizi hakkında:

    let array1 = [1,2,3]
    let array2 = array1
    array1.withUnsafeBufferPointer { (point) in
        print(point) // UnsafeBufferPointer(start: 0x00006000004681e0, count: 3)
    }
    array2.withUnsafeBufferPointer { (point) in
        print(point) // UnsafeBufferPointer(start: 0x00006000004681e0, count: 3)
    }

1
günümü kurtardım. "En yararlı son satın alma" bir rozet olmalıdır
Anton Tropashko

Gerçekten de, bu benim için baskı yapan tek yaklaşım self?.array.
Rostyslav Druzhchenko

4

Ben tamsayı olarak işaretçi adresi almak için bir yol arıyordum diğer cevaplar, gayet iyi:

let ptr = unsafeAddressOf(obj)
let nullPtr = UnsafePointer<Void>(bitPattern: 0)

/// This gets the address of pointer
let address = nullPtr.distanceTo(ptr) // This is Int

Sadece küçük bir takip.


Swift 3 için bu cevabın bir sürümü için aşağıya bakın
RenniePet

3

@Drew'un sağladığı yanıt yalnızca sınıf türü için kullanılabilir.
@Nschum tarafından sağlanan yanıt yalnızca yapı türü için olabilir.

Ancak, değer türü öğesiyle bir dizinin adresini almak için ikinci yöntemi kullanırsanız. Swift, tüm diziyi kopyalayacaktır çünkü Swift dizisinde yazma üzerine kopyalama ve Swift, kontrolü C / C ++ 'a ( &adres almak için kullanarak tetiklenir) geçtikten sonra bu şekilde davrandığından emin olamaz . Bunun yerine ilk yöntemi kullanırsanız, otomatik olarak dönüştürülecektir Array, NSArrayki bu kesinlikle istemediğimiz bir şeydir.

Bulduğum en basit ve birleşik yol lldb komutunu kullanmak frame variable -L yourVariableName.

Veya cevaplarını birleştirebilirsiniz:

func address(o: UnsafePointer<Void>) {
    let addr = unsafeBitCast(o, Int.self)
    print(NSString(format: "%p", addr))
}

func address<T: AnyObject>(o: T) -> String{
    let addr = unsafeBitCast(o, Int.self)
    return NSString(format: "%p", addr) as String
}

3

Bu Swift 3 için.

@CharlieMonroe gibi adresi bir tamsayı olarak almak istedim. Özellikle, bir iş parçacığı adının kullanılabilir olduğu durumlar için, tanılama günlüğü modülünde bir iş parçacığı kimliği olarak kullanmak için bir iş parçacığı nesnesinin adresini istedi.

Charlie Monroe'nun koduna dayanarak, şimdiye kadar bulduğum şey. Ama dikkat et, Swift için çok yeniyim, bu doğru olmayabilir ...

  // Convert the memory address of the current Thread object into an Int for use as a thread ID
  let objPtr = Unmanaged.passUnretained(Thread.current).toOpaque()
  let onePtr = UnsafeMutableRawPointer(bitPattern: 1)!  // 1 used instead of 0 to avoid crash
  let rawAddress : Int64 = onePtr.distance(to: objPtr) + 1  // This may include some high-order bits
  let address = rawAddress % (256 * 1024 * 1024 * 1024)  // Remove high-order bits

Son ifade orada çünkü o olmadan ben 0x60000007DB3F gibi adresler alıyordu. Son deyimdeki modulo işlemi bunu 0x7DB3F'ye dönüştürür.


3

Swift 3'teki çözümüm

extension MyClass: CustomStringConvertible {
    var description: String {
        return "<\(type(of: self)): 0x\(String(unsafeBitCast(self, to: Int.self), radix: 16, uppercase: false))>"
    }
}

bu kod varsayılan açıklama gibi açıklama oluşturur <MyClass: 0x610000223340>


2

Bu kesinlikle en hızlı ya da en güvenli yol değil. Ama benim için çalışıyor. Bu, herhangi bir nsobject alt sınıfının bu özelliği benimsemesine izin verecektir.

public extension NSObject {
    public var memoryAddress : String? {
        let str = "\(self.self)".components(separatedBy: ": ")
        guard str.count > 1 else { return nil }
        return str[1].replacingOccurrences(of: ">", with: "")            
    }
}

//usage 
let foo : String! = "hello"
Swift.print(foo.memoryAddress) // prints 0x100f12980

geribildirim için teşekkürler Jeff, cevabı güncelleyeceğim
Charlton Provatas

1
Boşver! Benim hatamdı! Kodunuz saf bir Swift sınıfıyla iyi çalışır. Hata için üzgünüm.
Jeff
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.