Imagine a class Fruit:
class Fruit: NSObject {
override var description:String {
return super.description
}
}
var apple = Fruit()
var banana = F
Any subclass of NSObject
inherits the
description method of NSObject
(which is defined in the NSObjectProtocol
):
class Foo1 : NSObject { }
print(Foo1())
//
This "default implementation" prints the class name and the memory address of the object, see for example Friday Q&A 2013-01-25: Let's Build NSObject, where it is shown how the Objective-C implementation could look like:
- (NSString *)description
{
return [NSString stringWithFormat: @"<%@: %p>", [self class], self];
}
The %p
format prints the value of a pointer as a hexadecimal number,
preceded by 0x
.
To mimic that in Swift, we can use
String(reflecting: self.dynamicType)
which returns the fully-qualified class name as a string, andunsafeAddressOf(self)
which returns a pointer to the storage
of the object.Example (using square brackets []
to demonstrate that the
overridden method is used):
class Foo2 : NSObject {
override var description : String {
let className = String(reflecting: self.dynamicType)
let address = unsafeAddressOf(self)
return String(format: "[%@: %p]", className, address)
}
}
print(Foo2())
// [MyProject.Foo2: 0x100613310]
class Foo3 : Foo2 { }
print(Foo3())
// [MyProject.Foo3: 0x102000540]
This works for "pure Swift classes" as well, because no Foundation methods are used:
class Bar : CustomStringConvertible {
var description : String {
let className = String(reflecting: self.dynamicType)
let address = unsafeAddressOf(self)
return String(format: "[%@: %p]", className, address)
}
}
print(Bar())
// [MyProject.Bar: 0x102001200]
Note that (as already mentioned in above comments), the hash value
of an object is not necessarily identical to the memory address.
A simple example is NSArray()
whose hash value is just the number
of elements:
let array = NSArray(objects: 1, 2, 3)
print(unsafeAddressOf(array)) // 0x00000001020011a0
print(array.hashValue) // 3
Update for Swift 3:
class Bar : CustomStringConvertible {
var description : String {
let className = String(reflecting: type(of: self))
let address = Unmanaged.passUnretained(self).toOpaque()
return "[\(className): \(address)]"
}
}