239

Is there anyway to simulate the [NSString stringWithFormat:@"%p", myVar], from Objective-C, in the new Swift language?

For example:

let str = "A String"
println(" str value \(str) has address: ?")
Paulo Mattos
  • 18,845
  • 10
  • 77
  • 85
apouche
  • 9,703
  • 6
  • 40
  • 45
  • 2
    In `[NSString stringWithFormat:@"%p", myVar]`, `myVar` must be a pointer. In your Swift code, `str` is not a pointer. So the comparison doesn't apply. – user102008 Aug 11 '14 at 06:45
  • 8
    It's worth noting that, at least when I'm typing this, the above two comments are incorrect. – Ky - Dec 12 '16 at 13:43

15 Answers15

340

Note: This is for reference types.

Swift 4/5:

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

Prints the memory address of someVar. (thanks to @Ying)


Swift 3.1:

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

Prints the memory address of someVar.


Community
  • 1
  • 1
Woodstock
  • 22,184
  • 15
  • 80
  • 118
  • 4
    Xcode 8.2.1 autocorrect is telling me it is now `print(Unmanaged.passUnretained(someVar as AnyObject).toOpaque())` – Jeff Feb 23 '17 at 03:36
  • 3
    Wouldn't this be true only if the someVar is an object. If someVar happens to be a value type such as a struct, this will give a different address every time it is executed. – OutOnAWeekend Jul 09 '17 at 12:53
  • 5
    @OutOnAWeekend You're right, most probably because the structure is copied when passed as an argument. Using `Unmanaged` it can be done like this: `print(Unmanaged.fromOpaque(&myStruct).toOpaque())`. – nyg Aug 19 '17 at 17:15
  • @OutOnAWeekend also, it only really matters for reference types right? – Woodstock Aug 20 '17 at 11:05
  • 3
    As of Swift 4, I was able to get this incantation to print as well - `Unmanaged.passUnretained(someVar).toOpaque()`(no need generic specification) – Ying Mar 09 '18 at 18:08
  • 4
    The Swift 4 answer is perfect. If you also wanted to get the string representation without printing, I'd recommend adding `debugDescription` to the end of it. – Patrick Aug 14 '18 at 05:44
  • 1
    This should be considered the proper answer. Using `withUnsafePointer` lead me to a different pointer, it does not match the debugger pointer value. I think `withUnsafePointer` returns the pointer of the variable that old the pointer to the object. – Gabriele Apr 05 '19 at 10:47
  • Thank you for the answer. I encapsulated the functionality into a util `Address`: ```swift struct Address: CustomStringConvertible { let description: String init(_ instance: Instance) { self.description = "\(Unmanaged.passUnretained(instance).toOpaque())" } } ``` This allows you to easily print the memory address: ```swift print("Address of object is \(Address(myObj))") ``` – cfergie May 31 '23 at 07:37
135

Swift 2

This is now part of the standard library: 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

For Swift 3, use withUnsafePointer:

var str = "A String"
withUnsafePointer(to: &str) {
    print(" str value \(str) has address: \($0)")
}
Drew
  • 8,675
  • 6
  • 43
  • 41
  • Introduced in Swift 2.0. – Murray Sagal Jul 25 '15 at 19:44
  • How to print address of the pointer itself. `var str = "String"` I want to print memory address used to store pointer to the "String". str in this case. – Swift Hipster Dec 15 '15 at 06:11
  • 2
    unsafeAddressOf() works only for class types (as @Nick points out below). Thus, this answer works only if Foundation is imported and String is bridged to NSString. In plain Swift, String is a value type and unsafeAddressOf cannot be used to take its address (the attempt results in a compile error). – Stephen Schaub Jul 25 '16 at 14:50
  • Removed in Swift 3.0. – Slipp D. Thompson Aug 24 '16 at 17:16
  • 30
    What if I want to print address of **immutable** value with Swift 3? `withUnsafePointer` results in `cannot pass immutable value as inout argument` error . – Alexander Vasenin Aug 31 '16 at 09:10
  • If you have an address of a value, it's no longer immutable, because you can set raw memory at that address to mutate the value. There has been discussion about allowing this "anyway", with the penalty of UB if the memory is modified (even transiently), but introducing new kinds of UB is not exactly a high priority for Swift at present. For the vast majority of usecases, promoting to mutable is the right solution, unless you have much stronger guarantees than pointer usecases generally imply. – Drew Aug 31 '16 at 14:41
  • 17
    Even though it's accepted and highest voted answer, it still gives **wrong** results. Example: `print(self.description)` prints ``, we use it as a reference. `var mutableSelf = self; withUnsafePointer(to: &mutableSelf) { print(String(format: "%p", $0)) }` prints `0x16fde4028` which is clearly different address. Can anybody explain why? – Alexander Vasenin Aug 04 '17 at 05:24
  • 4
    BTW, this prints `0x101c1d580` as expected: `print(String(format: "%p", unsafeBitCast(self, to: Int.self)))` – Alexander Vasenin Aug 04 '17 at 05:25
  • @AlexanderVasenin The reason it's not working for you is that you're using a class instance (UIViewController) whereas Drew is using a structure instance (String). Check my answer for a more detailed answer. By the way, yes, the answer gives wrong results when used on class instances. – nyg Aug 21 '17 at 08:10
  • 11
    @nyg Your answer gave me a clue for the actual error cause: `UnsafePointer` is a struct, so in order to print _the address it's pointing to_ (and not the struct itself) you have to print `String(format: "%p", $0.pointee)`! – Alexander Vasenin Aug 29 '17 at 14:11
  • 2
    The printed address and the debugger one does not match. I think `withUnsafePointer` return the pointer address of the variable that hold the object you want to print the address. Look here https://stackoverflow.com/a/41666807/621695 – Gabriele Apr 05 '19 at 10:50
50

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
Rog
  • 17,070
  • 9
  • 50
  • 73
LombaX
  • 17,265
  • 5
  • 52
  • 77
  • yes, the pointer has to exsit but not only for compatibility reasons as you refered. the pointers usually used by the operating system. even if the language is high-level language the pointers must exist in any language in any time in the operating system's engine. – holex Jun 26 '14 at 11:01
  • I said "for compatibility reason AND because the runtime needs it" :-) the second statement recaps what you are saying (I assume that a programmer knows and understand it, so I spent few words) – LombaX Jun 26 '14 at 11:03
  • I assume this doesn't apply anymore? – aleclarson Sep 22 '14 at 13:21
  • Yes. I edited the correct answer from @Drew into it. – Rog Jul 06 '15 at 10:24
  • @LombaX we can only print address of reference type? Can't I print address of variables? – abhimanyuaryan Jul 14 '15 at 23:18
  • @LombaX what I am understanding (and trying out in a playground) is unsafeAddressOf will create a new pointer to the object and hand it over to me and trying to print its address (using .debugDescription) will actually print the address of this pointer and not the object it is pointing to. How do I print the address of the object itself. – Ishaan Sejwal Aug 23 '16 at 09:37
  • @IshaanSejwal no, unsafeAddressOf doesn't create a new pointer. It simply returns the memory address of the storage associated to the object, not its pointer address – LombaX Aug 23 '16 at 13:12
37

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 we deal either with value types (structures) or reference types (classes). When doing:

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

Some memory is allocated at address X, and at this address we will find the value 42. Doing &n creates a pointer pointing to address X, therefore &n tells us where n is located.

(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

When doing:

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

Memory is allocated in two places:

  • at address Y where the class instance data is located and
  • at address X where the class instance reference is located.

As said, classes are reference types: so the value of c is located at address X, at which we'll find the value of Y. And at address Y + 16 we'll find foo and at address Y + 24 we'll find bar (at + 0 and + 8 we'll find type data and reference counts, I can't tell you much more about this...).

(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 is 42 (foo) and 0x54 is 84 (bar).

In both cases, using &n or &c will give us address X. For value types, that's what we want, but isn't for reference types.

When doing:

let referencePointer = UnsafeMutablePointer<C>(&c)

We create a pointer on the reference, i.e. a pointer that points to address X. Same thing when using 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)

Now that we have a better understanding of what goes on under the hood, and that we now that at address X we'll find address Y (which is the one we want) we can do the following to get it:

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

Verifying:

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

There are other ways to do this:

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

toOpaque() actually calls unsafeBitCast(c, to: UnsafeMutableRawPointer.self).

I hope this helped... it did for me .

nyg
  • 2,380
  • 3
  • 25
  • 40
  • Just noticed that while trying to print the address of the same struct through 2 different instances of `MemoryLocation` produces 2 different addresses. – user1046037 Sep 12 '17 at 12:12
  • @user1046037 Thanks, made the change for the class init. I also get two different addresses, but only when I use an empty struct. Using empty struct always gives me weird results. My guess is the compiler makes some optimisations... – nyg Sep 12 '17 at 12:19
  • @user1046037 Check: https://pastebin.com/mpd3ujw2. Apparently, all empty struct point to the same memory address. However, when we want to store the pointer in a variable it will create a copy of it (or of the struct?)... – nyg Sep 12 '17 at 12:50
  • That's interesting but when printed twice it prints the different memory addresses. Same is the case with above answers as well. – user1046037 Sep 12 '17 at 13:00
  • @user1046037 I'm not sure I understand what you mean, do you have some code? (I always get the same memory address) – nyg Sep 16 '17 at 21:11
  • when you use an empty struct `struct S {}`. I was getting different memory addresses. Actually there is less significance for trying to know the memory address of a value type. For value types the emphasis is more on value and not on identity. Example: Int(5) and another Int(5), would be more meaningful to compare for equality rather than identity (meaning memory address) as value types are not meant for denoting identity – user1046037 Sep 17 '17 at 00:49
  • Thank you for the answer! Is it possible to use `MemoryAddress` for generic structures (for example `struct LinkedList`)? – derpoliuk Mar 29 '21 at 16:36
  • I am trying to do an extension on a SwiftUI View`extension View { var memoryAddress: Int { MemoryAddress(of: &self).intValue } }` but get error 'Cannot pass immutable value as inout argument: 'self' is immutable' .. is there a workaround? – andrewz May 11 '22 at 00:56
28

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

Usage:

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

print("nil: \(String.pointer(nil))")
// nil: nil
neoneye
  • 50,398
  • 25
  • 166
  • 151
  • This answer is incorrect. If you make two instances of the same class it'll return the same memory address for both instances. `Unmanaged.passUnretained(myObject).toOpaque()` works properly instead. – Padraig Mar 02 '18 at 00:04
  • @Padraig Thanks, I have updated with your code. Sadly it now takes an `AnyObject` parameter. I would prefer `Any` as the input type. – neoneye Mar 03 '18 at 07:41
  • 1
    Why would an Any that's not AnyObject have a pointer? – kocodude Sep 23 '20 at 01:22
23

To get the (heap) address of an object

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

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

(Edit: Swift 1.2 now includes a similar function called unsafeAddressOf.)

In Objective-C this would be [NSString stringWithFormat:@"%p", o].

o is a reference to the instance. So if o is assigned to another variable o2, the returned address for o2 will be the same.

This doesn't apply to structs (including String) and primitive types (like Int), because those live directly on the stack. But we can retrieve the location on the stack.

To get the (stack) address of a struct, build-in type or object reference

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 this would be [NSString stringWithFormat:@"%p", &o] or [NSString stringWithFormat:@"%p", &i].

s is struct. So if s is assigned to another variable s2, the value will be copied and the returned address for s2 will be different.

How it fits together (pointer recap)

Like in Objective-C, there are two different addresses associated with o. The first is the location of the object, the second is the location of the reference (or pointer) to the object.

Yes, this means that the content of address 0x7fff5fbfe658 is the number 0x6100000011d0 as the debugger can tell us:

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

So, except for strings being structs, internally this all pretty much works the same as in (Objective-)C.

(Current as of Xcode 6.3)

nschum
  • 15,322
  • 5
  • 58
  • 56
  • Hmm. Getting the stack address of an object's property isn't consistent. Any ideas? [Check out this gist!](https://gist.github.com/aleclarson/62da17f7129b4e7c5b69) – aleclarson Sep 22 '14 at 13:53
  • The object's properties are on the heap, not the stack. When you pass a class instance's property as an UnsafePointer, Swift actually copies the value first and you get the address of the copy. I suspect that is to prevent C code from circumventing the object's interface and causing an inconsistent state. I don't know if there is a way around that. – nschum Sep 22 '14 at 15:46
  • Here's [a thread I created on the Apple Developer Forums](https://devforums.apple.com/thread/247020?tstart=0). Some good replies in there. – aleclarson Sep 22 '14 at 16:09
22

Reference Types:

  • It makes sense to get the memory address of a reference type as it represents identity.
  • === identity operator is used to check 2 objects point to the same reference.
  • Use ObjectIdentifier to get the memory address

Code:

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

Value Types:

  • The need to get the memory address of a value type is not of much significance (as it is a value) and the emphasis would be more on the equality of the value.
user1046037
  • 16,755
  • 12
  • 92
  • 138
18

Just use this:

print(String(format: "%p", object))
pavelcauselov
  • 519
  • 5
  • 10
  • If you get a compiler complaint about "`MyClass?`" does not conform to CVarArg, you can do `extension Optional : CVarArg { }`. Otherwise this seems to print addresses without all the "unsafe" insanity of the other answers. – Devin Lane Oct 10 '19 at 20:49
  • 2
    It requires implementation of `var _cVarArgEncoding: [Int]` on `CVarArg`. Not clear how that should be implemented. – Yuchen Jan 06 '20 at 01:34
13

If you just want to see this in the debugger and not do anything else with it, there's no need to actually get the Int pointer. To get the string representation of an object's address in memory, just use something like this:

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

Example usage:

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

Additionally, remember that you can simply print an object without overriding its description, and it will show its pointer address alongside more descriptive (if oft cryptic) text.

print(self, "Doing something else...")
// Prints like: <MyModule.MyClass: 0x7fd190d0f270> Doing something else...
// Sometimes like: <_TtCC14__lldb_expr_668MyModule7MyClass: 0x7fd190d0f270> Doing something else...
Ky -
  • 30,724
  • 51
  • 192
  • 308
13

In Swift4 about 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)
    }
SenKe
  • 346
  • 3
  • 10
7

The answer @Drew provide can only be used for class type.
The answer @nschum provide can only be for struct type.

However if you use the second method to get address of a array with value type element. Swift will copy the whole array because in Swift array is copy-on-write and Swift can't make sure it behave this way once it pass control over to C/C++ (Which is trigger by using & to get address). And if you use first method instead , it will automatically convert Array to NSArray which is surely something we don't want.

So the most simple and unified way I found is using lldb instruction frame variable -L yourVariableName.

Or you can combine their answers:

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
}
Nick Allen
  • 1,647
  • 14
  • 20
4

The other answers are fine, though I was looking for a way to get the pointer address as an integer:

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

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

Just a little follow-up.

Charlie Monroe
  • 1,210
  • 9
  • 24
4

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>

EvGeniy Ilyin
  • 1,817
  • 1
  • 21
  • 38
3

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.

RenniePet
  • 11,420
  • 7
  • 80
  • 106
1

This is certainly not the fastest or safest way to go about it. But it works for me. This will allow for any nsobject subclass to adopt this property.

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
Charlton Provatas
  • 2,184
  • 25
  • 18