How can you mimic the description output?

后端 未结 2 992
感情败类
感情败类 2021-01-27 20:06

Imagine a class Fruit:

class Fruit: NSObject {
    override var description:String {
        return super.description
    }
}

var apple = Fruit()
var banana = F         


        
2条回答
  •  有刺的猬
    2021-01-27 20:42

    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, and
    • unsafeAddressOf(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)]"
        }
    }
    

提交回复
热议问题