Is there anyway to simulate the [NSString stringWithFormat:@\"%p\", myVar]
, from Objective-C, in the new Swift language?
For example:
le
Just use this:
print(String(format: "%p", object))
===
identity operator is used to check 2 objects point to the same reference.ObjectIdentifier
to get the memory addressclass 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
My solution on Swift 3
extension MyClass: CustomStringConvertible {
var description: String {
return "<\(type(of: self)): 0x\(String(unsafeBitCast(self, to: Int.self), radix: 16, uppercase: false))>"
}
}
this code create description like default description
<MyClass: 0x610000223340>
This is for Swift 3.
Like @CharlieMonroe I wanted to get the address as an integer. Specifically, I wanted the address of a Thread object for use as a thread ID in a diagnostic logging module, for situations where no thread name was available.
Based on Charlie Monroe's code, here's what I've come up with so far. But beware, I'm very new to Swift, this may not be correct ...
// 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
The last statement is there because without it I was getting addresses like 0x60000007DB3F. The modulo operation in the last statement converts that into 0x7DB3F.
Note: This is for reference types.
print(Unmanaged.passUnretained(someVar).toOpaque())
Prints the memory address of someVar. (thanks to @Ying)
print(Unmanaged<AnyObject>.passUnretained(someVar as AnyObject).toOpaque())
Prints the memory address of someVar.
Note that this answer was quite old. Many of the methods it describes no longer work. Specifically .core
cannot be accessed anymore.
However @drew's answer is correct and simple:
This is now part of the standard library: unsafeAddressOf.
So the answer to your questions is:
println(" str value \(str) has address: \(unsafeAddressOf(str))")
Here is the original answer that was marked correct (for posterity/politeness):
Swift "hides" pointers, but they still exists under the hood. (because the runtime needs it, and for compatibility reasons with Objc and C)
There are few things to know however, but first how to print the memory address of a Swift String?
var aString : String = "THIS IS A STRING"
NSLog("%p", aString.core._baseAddress) // _baseAddress is a COpaquePointer
// example printed address 0x100006db0
This prints the memory address of the string, if you open XCode -> Debug Workflow -> View Memory and go to the printed address, you will see the raw data of the string. Since this is a string literal, this is a memory address inside the storage of the binary (not stack or heap).
However, if you do
var aString : String = "THIS IS A STRING" + "This is another String"
NSLog("%p", aString.core._baseAddress)
// example printed address 0x103f30020
This will be on the stack, because the string is created at runtime
NOTE: .core._baseAddress is not documented, I found it looking in the variable inspector, and it may be hidden in the future
_baseAddress is not available on all types, here another example with a CInt
var testNumber : CInt = 289
takesInt(&testNumber)
Where takesInt
is a C helper function like this
void takesInt(int *intptr)
{
printf("%p", intptr);
}
On the Swift side, this function is takesInt(intptr: CMutablePointer<CInt>)
, so it takes a CMutablePointer to a CInt, and you can obtain it with &varname
The function prints 0x7fff5fbfed98
, an at this memory address you will find 289 (in hexadecimal notation). You can change its content with *intptr = 123456
Now, some other things to know.
String, in swift, is a primitive type, not an object.
CInt is a Swift type mapped to the C int Type.
If you want the memory address of an object, you have to do something different.
Swift has some Pointer Types that can be used when interacting with C, and you can read about them here: Swift Pointer Types
Moreover, you can understand more about them exploring their declaration (cmd+click on the type), to understand how to convert a type of pointer into another
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
is a C helper function I created, with this implementation
void printptr(void ** ptr)
{
printf("%p", *ptr);
}
Again, an example of the address printed: 0x6000000530b0
, and if you go through memory inspector you will find your NSString
One thing you can do with pointers in Swift (this can even be done with inout parameters)
func playWithPointer (stringa :AutoreleasingUnsafePointer<NSString>)
{
stringa.memory = "String Updated";
}
var testString : NSString = "test string"
println(testString)
playWithPointer(&testString)
println(testString)
Or, interacting with 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