¿Hay alguna forma de simular [NSString stringWithFormat:@"%p", myVar]
, desde Objective-C, en el nuevo lenguaje Swift?
Por ejemplo:
let str = "A String"
println(" str value \(str) has address: ?")
swift
debugging
memory-address
apouche
fuente
fuente
[NSString stringWithFormat:@"%p", myVar]
,myVar
debe ser un puntero. En su código Swift,str
no es un puntero. Entonces la comparación no se aplica.Respuestas:
Swift 2
Esto es ahora parte de la biblioteca estándar:
unsafeAddressOf
.Swift 3
Para Swift 3, use
withUnsafePointer
:fuente
withUnsafePointer
da como resultado uncannot pass immutable value as inout argument
error.print(self.description)
impresiones<MyViewController: 0x101c1d580>
, lo usamos como referencia.var mutableSelf = self; withUnsafePointer(to: &mutableSelf) { print(String(format: "%p", $0)) }
Impresiones0x16fde4028
que es claramente diferente dirección. ¿Alguien puede explicar por qué?0x101c1d580
como se esperaba:print(String(format: "%p", unsafeBitCast(self, to: Int.self)))
UnsafePointer
es una estructura, por lo que para imprimir la dirección a la que apunta (y no la estructura en sí) ¡tiene que imprimirString(format: "%p", $0.pointee)
!Nota: Esto es para tipos de referencia.
Swift 4/5:
Imprime la dirección de memoria de someVar. (gracias a @Ying)
Swift 3.1:
Imprime la dirección de memoria de someVar.
fuente
print(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
Unmanaged
que se puede hacer así:print(Unmanaged<AnyObject>.fromOpaque(&myStruct).toOpaque())
.Unmanaged.passUnretained(someVar).toOpaque()
(sin necesidad de una especificación genérica)debugDescription
al final.Tenga en cuenta que esta respuesta era bastante antigua. Muchos de los métodos que describe ya no funcionan. Específicamente
.core
ya no se puede acceder.Sin embargo, la respuesta de @ drew es correcta y simple:
Entonces la respuesta a sus preguntas es:
Aquí está la respuesta original que se marcó correcta (para posteridad / cortesía):
Los punteros rápidos "ocultan", pero todavía existen debajo del capó. (porque el tiempo de ejecución lo necesita, y por razones de compatibilidad con Objc y C)
Sin embargo, hay algunas cosas que debe saber, pero primero, ¿cómo imprimir la dirección de memoria de una cadena rápida?
Esto imprime la dirección de memoria de la cadena, si abre XCode -> Debug Workflow -> View Memory y va a la dirección impresa, verá los datos sin procesar de la cadena. Como se trata de un literal de cadena, se trata de una dirección de memoria dentro del almacenamiento del binario (no de pila o montón).
Sin embargo, si lo haces
Esto estará en la pila, porque la cadena se crea en tiempo de ejecución
NOTA: .core._baseAddress no está documentado, lo encontré buscando en el inspector de variables y puede estar oculto en el futuro
_baseAddress no está disponible en todos los tipos, aquí otro ejemplo con un CInt
¿Dónde
takesInt
está una función auxiliar de C como esta?En el lado de Swift, esta función es
takesInt(intptr: CMutablePointer<CInt>)
, por lo que toma un CMutablePointer a un CInt, y puede obtenerlo con & varnameLa función se imprime
0x7fff5fbfed98
, y en esta dirección de memoria encontrará 289 (en notación hexadecimal). Puedes cambiar su contenido con*intptr = 123456
Ahora, algunas otras cosas para saber.
La cadena, en forma rápida, es un tipo primitivo, no un objeto.
CInt es un tipo Swift asignado al tipo C int.
Si desea la dirección de memoria de un objeto, debe hacer algo diferente.
Swift tiene algunos tipos de puntero que se pueden usar al interactuar con C, y puede leer sobre ellos aquí: Tipos de puntero Swift
Además, puede comprender más acerca de cómo explorar su declaración (cmd + clic en el tipo), para comprender cómo convertir un tipo de puntero a otro
printptr
es una función auxiliar de C que creé, con esta implementaciónNuevamente, un ejemplo de la dirección impresa:
0x6000000530b0
y si pasa por el inspector de memoria encontrará su NSStringUna cosa que puedes hacer con punteros en Swift (esto incluso se puede hacer con parámetros inout)
O, interactuando con Objc / c
fuente
Para obtener la dirección (montón) de un objeto
( Editar: Swift 1.2 ahora incluye una función similar llamada
unsafeAddressOf
).En Objective-C esto sería
[NSString stringWithFormat:@"%p", o]
.o
es una referencia a la instancia. Entonces, sio
se asigna a otra variableo2
, la dirección devueltao2
será la misma.Esto no se aplica a estructuras (incluidos
String
) y tipos primitivos (comoInt
), porque esos viven directamente en la pila. Pero podemos recuperar la ubicación en la pila.Para obtener la dirección (pila) de una estructura, tipo incorporado o referencia de objeto
En Objective-C esto sería
[NSString stringWithFormat:@"%p", &o]
o[NSString stringWithFormat:@"%p", &i]
.s
es struct. Entonces, sis
se asigna a otra variables2
, el valor se copiará y la dirección devueltas2
será diferente.Cómo encaja (resumen del puntero)
Al igual que en Objective-C, hay dos direcciones diferentes asociadas con
o
. El primero es la ubicación del objeto, el segundo es la ubicación de la referencia (o puntero) al objeto.Sí, esto significa que el contenido de la dirección 0x7fff5fbfe658 es el número 0x6100000011d0 como el depurador puede decirnos:
Entonces, excepto que las cadenas son estructuras, internamente todo esto funciona casi igual que en (Objective-) C.
(Actual a partir de Xcode 6.3)
fuente
TL; DR
( Esencia )
En Swift tratamos con tipos de valor (estructuras) o tipos de referencia (clases). Al hacer:
Se asigna algo de memoria en la dirección X, y en esta dirección encontraremos el valor 42. Hacer
&n
crea un puntero que apunta a la dirección X, por lo tanto,&n
nos dice dónden
está ubicado.Al hacer:
La memoria se asigna en dos lugares:
Como se dijo, las clases son tipos de referencia: por lo tanto, el valor de
c
se encuentra en la dirección X, donde encontraremos el valor de Y. Y en la dirección Y + 16 encontraremosfoo
y en la dirección Y + 24 encontraremosbar
( en + 0 y + 8 encontraremos datos de tipo y recuentos de referencias, no puedo decirle mucho más sobre esto ...).0x2a
es 42 (foo) y0x54
es 84 (bar).En ambos casos, usar
&n
o&c
nos dará la dirección X. Para los tipos de valor, eso es lo que queremos, pero no para los tipos de referencia.Al hacer:
Creamos un puntero en la referencia, es decir, un puntero que apunta a la dirección X. Lo mismo cuando se usa
withUnsafePointer(&c) {}
.Ahora que tenemos una mejor comprensión de lo que sucede debajo del capó, y ahora que en la dirección X encontraremos la dirección Y (que es la que queremos), podemos hacer lo siguiente para obtenerla:
Verificando:
Hay otras formas de hacer esto:
toOpaque()
En realidad llamaunsafeBitCast(c, to: UnsafeMutableRawPointer.self)
.Espero que esto haya ayudado ... lo hizo para mí 😆.
fuente
MemoryLocation
produce 2 direcciones diferentes.Tipos de referencia:
===
El operador de identidad se utiliza para comprobar que 2 objetos apuntan a la misma referencia.ObjectIdentifier
para obtener la dirección de memoriaCódigo:
Tipos de valor:
fuente
Solo usa esto:
fuente
MyClass?
" no se ajusta a CVarArg, puede hacerloextension Optional : CVarArg { }
. De lo contrario, esto parece imprimir direcciones sin toda la locura "insegura" de las otras respuestas.var _cVarArgEncoding: [Int]
onCVarArg
. No está claro cómo se debe implementar eso.Si solo quiere ver esto en el depurador y no hacer nada más con él, no hay necesidad de obtener el
Int
puntero. Para obtener la representación de cadena de la dirección de un objeto en la memoria, simplemente use algo como esto:Ejemplo de uso:
Además, recuerde que simplemente puede imprimir un objeto sin anularlo
description
, y mostrará su dirección de puntero junto con un texto más descriptivo (aunque a menudo críptico).fuente
Swift 5
Uso:
fuente
Unmanaged.passUnretained(myObject).toOpaque()
funciona correctamente en su lugar.AnyObject
parámetro. PreferiríaAny
como el tipo de entrada.En Swift4 sobre Array:
fuente
self?.array
.Las otras respuestas están bien, aunque estaba buscando una manera de obtener la dirección del puntero como un entero:
Solo un pequeño seguimiento.
fuente
La respuesta que proporciona @Drew solo se puede usar para el tipo de clase.
La respuesta que proporciona @nschum solo puede ser para el tipo de estructura.
Sin embargo, si utiliza el segundo método para obtener la dirección de una matriz con un elemento de tipo de valor. Swift copiará toda la matriz porque en la matriz Swift se copia y escribe y Swift no puede asegurarse de que se comporte de esta manera una vez que pasa el control a C / C ++ (que se activa utilizando
&
para obtener la dirección). Y si usa el primer método, se convertirá automáticamenteArray
enNSArray
algo que seguramente no queremos.Entonces, la forma más simple y unificada que encontré es usando la instrucción lldb
frame variable -L yourVariableName
.O puedes combinar sus respuestas:
fuente
Esto es para Swift 3.
Al igual que @CharlieMonroe, quería obtener la dirección como un número entero. Específicamente, quería la dirección de un objeto Thread para usar como ID de hilo en un módulo de registro de diagnóstico, para situaciones en las que no había un nombre de hilo disponible.
Basado en el código de Charlie Monroe, esto es lo que se me ocurrió hasta ahora. Pero cuidado, soy muy nuevo en Swift, esto puede no ser correcto ...
La última declaración está ahí porque sin ella estaba obteniendo direcciones como 0x60000007DB3F. La operación de módulo en la última instrucción convierte eso en 0x7DB3F.
fuente
Mi solución en Swift 3
este código crea una descripción como la descripción predeterminada
<MyClass: 0x610000223340>
fuente
Ciertamente, esta no es la forma más rápida o segura de hacerlo. Pero funciona para mí. Esto permitirá que cualquier subclase nsobject adopte esta propiedad.
fuente