Stampa veloce di un indirizzo di memoria variabile


166

Esiste un modo per simulare [NSString stringWithFormat:@"%p", myVar], da Objective-C, nel nuovo linguaggio Swift?

Per esempio:

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

2
In [NSString stringWithFormat:@"%p", myVar], myVardeve essere un puntatore. Nel tuo codice Swift, strnon è un puntatore. Quindi il confronto non si applica.
user102008

5
Vale la pena notare che, almeno quando sto scrivendo questo, i due commenti sopra sono errati.
Ben Leggiero,

Risposte:


112

Swift 2

Questo è ora parte della libreria standard: 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

Swift 3

Per Swift 3, utilizzare withUnsafePointer:

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

2
unsafeAddressOf () funziona solo per i tipi di classe (come sottolineato da @Nick di seguito). Pertanto, questa risposta funziona solo se viene importato Foundation e String viene collegato a NSString. In semplice Swift, String è un tipo di valore e unsafeAddressOf non può essere usato per prendere il suo indirizzo (il tentativo provoca un errore di compilazione).
Stephen Schaub,

29
Cosa succede se desidero stampare un indirizzo di valore immutabile con Swift 3? withUnsafePointerrisulta in cannot pass immutable value as inout argumenterrore.
Alexander Vasenin,

12
Anche se è accettata e la risposta più votata, dà comunque risultati errati . Esempio: print(self.description)stampe <MyViewController: 0x101c1d580>, lo usiamo come riferimento. var mutableSelf = self; withUnsafePointer(to: &mutableSelf) { print(String(format: "%p", $0)) }stampe con 0x16fde4028indirizzo chiaramente diverso. Qualcuno può spiegare perché?
Alexander Vasenin,

4
A proposito, questo stampa 0x101c1d580come previsto:print(String(format: "%p", unsafeBitCast(self, to: Int.self)))
Alexander Vasenin

8
@nyg La tua risposta mi ha dato un indizio sull'effettiva causa dell'errore: UnsafePointerè una struttura, quindi per stampare l'indirizzo a cui punta (e non la struttura stessa) devi stampare String(format: "%p", $0.pointee)!
Alexander Vasenin,

214

Nota: questo è per i tipi di riferimento.

Swift 4/5:

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

Stampa l'indirizzo di memoria di someVar. (grazie a @Ying)


Swift 3.1:

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

Stampa l'indirizzo di memoria di someVar.



2
La correzione automatica Xcode 8.2.1 mi sta dicendo che è oraprint(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
Jeff,

2
Questo non sarebbe vero solo se someVar è un oggetto. Se someVar sembra essere un tipo di valore come una struttura, questo darà un indirizzo diverso ogni volta che viene eseguito.
OutOnAWeekend

3
@OutOnAWeekend Hai ragione, molto probabilmente perché la struttura viene copiata quando passata come argomento. Utilizzando Unmanagedsi può fare in questo modo: print(Unmanaged<AnyObject>.fromOpaque(&myStruct).toOpaque()).
nyg

1
A partire da Swift 4, sono stato in grado di ottenere anche questo incantesimo da stampare - Unmanaged.passUnretained(someVar).toOpaque()(non sono necessarie specifiche generiche)
Ying

2
La risposta di Swift 4 è perfetta. Se anche tu volessi ottenere la rappresentazione in forma di stringa senza stamparla, ti consiglio di aggiungerla debugDescriptionalla fine.
Patrick,

51

Nota che questa risposta era piuttosto vecchia. Molti dei metodi descritti non funzionano più. In particolare .corenon è più possibile accedervi.

Tuttavia, la risposta di @ drew è corretta e semplice:

Questo fa ora parte della libreria standard: unsafeAddressOf.

Quindi la risposta alle tue domande è:

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

Ecco la risposta originale che è stata contrassegnata come corretta (per posteri / cortesia):

I puntatori rapidi "nascondono", ma esistono ancora sotto il cofano. (perché il runtime ne ha bisogno e per motivi di compatibilità con Objc e C)

Tuttavia, ci sono poche cose da sapere, ma prima come stampare l'indirizzo di memoria di una stringa Swift?

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

Questo stampa l'indirizzo di memoria della stringa, se apri XCode -> Debug Workflow -> Visualizza memoria e vai all'indirizzo stampato, vedrai i dati grezzi della stringa. Poiché si tratta di una stringa letterale, si tratta di un indirizzo di memoria all'interno della memoria del file binario (non stack o heap).

Tuttavia, se lo fai

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

    // example printed address 0x103f30020

Questo sarà nello stack, perché la stringa viene creata in fase di esecuzione

NOTA: .core._baseAddress non è documentato, l'ho trovato cercando nella finestra di ispezione delle variabili e potrebbe essere nascosto in futuro

_baseAddress non è disponibile su tutti i tipi, qui un altro esempio con un CInt

    var testNumber : CInt = 289
    takesInt(&testNumber)

Dov'è takesIntuna funzione di supporto C come questa

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

Sul lato Swift, questa funzione è takesInt(intptr: CMutablePointer<CInt>), quindi ci vuole un CMutablePointer a un CInt, e puoi ottenerlo con & varname

La funzione stampa 0x7fff5fbfed98, e a questo indirizzo di memoria troverai 289 (in notazione esadecimale). Puoi cambiarne il contenuto con*intptr = 123456

Ora, alcune altre cose da sapere.

String, in breve tempo, è un tipo primitivo, non un oggetto.
CInt è un tipo Swift associato al tipo C int.
Se vuoi l'indirizzo di memoria di un oggetto, devi fare qualcosa di diverso.
Swift ha alcuni tipi di puntatore che possono essere utilizzati quando si interagisce con C, e puoi leggerli qui: Tipi di puntatore Swift
Inoltre, puoi capire di più su di essi esplorando la loro dichiarazione (cmd + clic sul tipo), per capire come convertire un tipo di puntatore in un altro

    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 è una funzione di supporto C che ho creato, con questa implementazione

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

Ancora una volta, viene stampato un esempio dell'indirizzo:, 0x6000000530b0e se si passa attraverso la finestra di ispezione della memoria, si troverà il NSString

Una cosa che puoi fare con i puntatori in Swift (questo può essere fatto anche con i parametri inout)

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

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

Oppure, interagendo con Objc / c

// 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

sì, il puntatore deve uscire, ma non solo per motivi di compatibilità come indicato. i puntatori normalmente utilizzati dal sistema operativo. anche se la lingua è di alto livello, i puntatori devono esistere in qualsiasi lingua in qualsiasi momento nel motore del sistema operativo.
Holex,

Ho detto "per motivi di compatibilità E perché il runtime ne ha bisogno" :-) la seconda affermazione riassume ciò che stai dicendo (suppongo che un programmatore lo sappia e lo capisca, quindi ho trascorso poche parole)
LombaX,

Presumo che questo non si applichi più?
aleclarson,

Sì. Ho modificato la risposta corretta da @Drew.
Rog,

@LombaX possiamo solo stampare l'indirizzo del tipo di riferimento? Non riesco a stampare l'indirizzo delle variabili?
AbhimanyuAryan,

21

Per ottenere l'indirizzo (heap) di un oggetto

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

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

( Modifica: Swift 1.2 ora include una funzione simile chiamata unsafeAddressOf.)

In Objective-C questo sarebbe [NSString stringWithFormat:@"%p", o].

oè un riferimento all'istanza. Quindi, se oassegnato a un'altra variabile o2, l'indirizzo restituito per o2sarà lo stesso.

Questo non si applica alle strutture (inclusi String) e ai tipi primitivi (come Int), perché quelli vivono direttamente nello stack. Ma possiamo recuperare la posizione nello stack.

Per ottenere l'indirizzo (stack) di una struttura, un tipo incorporato o un riferimento a un oggetto

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

In Objective-C questo sarebbe [NSString stringWithFormat:@"%p", &o]o [NSString stringWithFormat:@"%p", &i].

sè struct. Quindi, se sassegnato a un'altra variabile s2, il valore verrà copiato e l'indirizzo restituito per s2sarà diverso.

Come si adatta insieme (riepilogo puntatore)

Come in Objective-C, sono associati due indirizzi diversi o . Il primo è la posizione dell'oggetto, il secondo è la posizione del riferimento (o puntatore) sull'oggetto.

Sì, questo significa che il contenuto dell'indirizzo 0x7fff5fbfe658 è il numero 0x6100000011d0 come può dirci il debugger:

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

Quindi, tranne che per le stringhe che sono strutture, internamente tutto ciò funziona praticamente come in (Obiettivo-) C.

(Attuale a partire da Xcode 6.3)


Hmm. Ottenere l'indirizzo dello stack della proprietà di un oggetto non è coerente. Qualche idea? Dai un'occhiata a questa idea!
aleclarson,

Le proprietà dell'oggetto sono nell'heap, non nello stack. Quando si passa la proprietà di un'istanza di classe come UnsafePointer, Swift effettivamente copia prima il valore e si ottiene l'indirizzo della copia. Sospetto che ciò impedisca al codice C di aggirare l'interfaccia dell'oggetto e causare uno stato incoerente. Non so se c'è un modo per aggirare questo.
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 )


In Swift abbiamo a che fare con tipi di valore (strutture) o tipi di riferimento (classi). Quando si fa:

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

Parte della memoria è allocata all'indirizzo X, e a questo indirizzo troveremo il valore 42. Fare &ncrea un puntatore che punta all'indirizzo X, quindi &nci dice dove nsi trova.

(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

Quando si fa:

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

La memoria è allocata in due posti:

  • all'indirizzo Y dove si trovano i dati dell'istanza della classe e
  • all'indirizzo X dove si trova il riferimento all'istanza di classe.

Come detto, le classi sono tipi di riferimento: quindi il valore di csi trova all'indirizzo X, al quale troveremo il valore di Y. E all'indirizzo Y + 16 troveremo fooe all'indirizzo Y + 24 troveremo bar( a + 0 e + 8 troveremo i dati di tipo e i conteggi dei riferimenti, non posso dirti molto di più su questo ...).

(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

0x2a è 42 (pippo) e 0x54 è 84 (bar).

In entrambi i casi, utilizzando &no&c ci fornirà l'indirizzo X. Per i tipi di valore, è quello che vogliamo, ma non per i tipi di riferimento.

Quando si fa:

let referencePointer = UnsafeMutablePointer<C>(&c)

Creiamo un puntatore sul riferimento, cioè un puntatore che punta a indirizzare X. Stessa cosa quando si usa withUnsafePointer(&c) {}.

(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)

Ora che abbiamo una migliore comprensione di ciò che accade sotto il cofano e che ora che all'indirizzo X troveremo l'indirizzo Y (che è quello che vogliamo) possiamo fare quanto segue per ottenerlo:

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

verifica:

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

Esistono altri modi per farlo:

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

toOpaque()chiama davvero unsafeBitCast(c, to: UnsafeMutableRawPointer.self).

Spero che questo abbia aiutato ... lo ha fatto per me 😆.


Ho appena notato che durante il tentativo di stampare l'indirizzo della stessa struttura attraverso 2 istanze diverse MemoryLocationproduce 2 indirizzi diversi.
user1046037

@ user1046037 Grazie, apportato la modifica per la classe init. Ottengo anche due indirizzi diversi, ma solo quando utilizzo una struttura vuota. L'uso di una struttura vuota mi dà sempre risultati strani. Suppongo che il compilatore faccia delle ottimizzazioni ...
nyg

@ user1046037 Verifica: pastebin.com/mpd3ujw2 . Apparentemente, tutte le strutture vuote puntano allo stesso indirizzo di memoria. Tuttavia, quando vogliamo memorizzare il puntatore in una variabile, ne verrà creata una copia (o della struttura?) ...
nyg

È interessante ma quando viene stampato due volte stampa i diversi indirizzi di memoria. Lo stesso vale per le risposte precedenti.
user1046037

@ user1046037 Non sono sicuro di aver capito cosa intendi, hai del codice? (Ricevo sempre lo stesso indirizzo di memoria)
nyg

15

Tipi di riferimento:

  • Ha senso ottenere l'indirizzo di memoria di un tipo di riferimento in quanto rappresenta l'identità.
  • === l'operatore di identità viene utilizzato per controllare 2 oggetti puntare allo stesso riferimento.
  • Utilizzare ObjectIdentifierper ottenere l'indirizzo di memoria

Codice:

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

Tipi di valore:

  • La necessità di ottenere l'indirizzo di memoria di un tipo di valore non è molto significativa (in quanto è un valore) e l'enfasi sarebbe più sull'uguaglianza del valore.

12

Usa questo:

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

Se ricevi un reclamo del compilatore su " MyClass?" non conforme a CVarArg, puoi farlo extension Optional : CVarArg { }. Altrimenti questo sembra stampare gli indirizzi senza tutta la follia "non sicura" delle altre risposte.
Devin Lane,

Richiede l'implementazione di var _cVarArgEncoding: [Int]on CVarArg. Non è chiaro come dovrebbe essere implementato.
Yuchen Zhong

10

Se vuoi solo vedere questo nel debugger e non fare nient'altro con esso, non è necessario ottenerlo Int puntatore. Per ottenere in memoria la rappresentazione in forma di stringa dell'indirizzo di un oggetto, basta usare qualcosa del genere:

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)
    }
}

Esempio di utilizzo:

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

Inoltre, ricorda che puoi semplicemente stampare un oggetto senza sovrascriverlo descriptione mostrerà il suo indirizzo di puntatore insieme a un testo più descrittivo (se spesso criptico).

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

1
Si prega di accompagnare eventuali downvotes con un commento che spieghi il perché, quindi io e chiunque altro veniamo qui sappiamo perché questa è una soluzione scadente :)
Ben Leggiero

1
Semplice e pulito!
badhanganesh,

9

Swift 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)
    }
}

Uso:

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

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

Questa risposta non è corretta Se si creano due istanze della stessa classe, verrà restituito lo stesso indirizzo di memoria per entrambe le istanze. Unmanaged.passUnretained(myObject).toOpaque()funziona correttamente invece.
Padraig

@Padraig Grazie, ho aggiornato con il tuo codice. Purtroppo ora ci vuole un AnyObjectparametro. Preferirei Anycome tipo di input.
Neoneye

6

In Swift4 sull'array:

    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
mi ha salvato la giornata. Dovrebbe esserci un badge "il più utile recente acquisizione"
Anton Tropashko,

In effetti, questo è l'unico approccio che ha stampato il mio self?.array.
Rostyslav Druzhchenko,

4

Le altre risposte vanno bene, anche se stavo cercando un modo per ottenere l'indirizzo del puntatore come numero intero:

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

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

Solo un piccolo seguito.


Vedi sotto per una versione di questa risposta per Swift 3.
RenniePet il

3

La risposta fornita da @Drew può essere utilizzata solo per il tipo di classe.
La risposta fornita da @nschum può essere solo per il tipo di struttura.

Tuttavia, se si utilizza il secondo metodo per ottenere l'indirizzo di un array con elemento tipo valore. Swift copierà l'intero array perché in Swift array è copia su scrittura e Swift non può assicurarsi che si comporti in questo modo una volta passato il controllo su C / C ++ (che viene attivato usando &per ottenere l'indirizzo). E se usi invece il primo metodo, si convertirà automaticamente in Arrayquello NSArrayche è sicuramente qualcosa che non vogliamo.

Quindi il modo più semplice e unificato che ho trovato è usare l'istruzione lldb frame variable -L yourVariableName.

Oppure puoi combinare le loro risposte:

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

Questo è per Swift 3.

Come @CharlieMonroe, volevo ottenere l'indirizzo come numero intero. In particolare, volevo che l'indirizzo di un oggetto Thread fosse utilizzato come ID thread in un modulo di registrazione diagnostica, per situazioni in cui non era disponibile il nome di thread.

Basato sul codice di Charlie Monroe, ecco cosa ho escogitato finora. Ma attenzione, sono molto nuovo su Swift, questo potrebbe non essere corretto ...

  // 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

L'ultima affermazione è lì perché senza di essa stavo ottenendo indirizzi come 0x60000007DB3F. L'operazione modulo nell'ultima istruzione lo converte in 0x7DB3F.


3

La mia soluzione su Swift 3

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

questo codice crea una descrizione come la descrizione predefinita <MyClass: 0x610000223340>


2

Questo non è certamente il modo più veloce o più sicuro per farlo. Ma funziona per me. Ciò consentirà a qualsiasi sottoclasse nsobject di adottare questa proprietà.

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

grazie per il feedback Jeff, aggiornerò la risposta
Charlton Provatas il

1
Non importa! È stato un mio errore! Il tuo codice funziona bene con una pura classe Swift. Scusa per l'errore.
Jeff
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.