您如何模仿描述输出?

How can you mimic the description output?

想象一个class水果:

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

var apple = Fruit()
var banana = Fruit()

print(apple)  // Output: <MyProject.Fruit: 0x7fa719627e00>
print(banana) // Output: <MyProject.Fruit: 0x7fa71962dab0>

问题:如何模仿这个输出?

我目前有:

class Fruit: NSObject {
    override var description:String {
        print(super.description)
        return "<\(NSStringFromClass(self.dynamicType)): 0x\(String(self.hash, radix:16))>"
    }
}

现在输出如下:

<MyProject.Fruit: 0x7fb958c289a0>
<MyProject.Fruit: 0x7fb958c289a0>
<MyProject.Fruit: 0x7fb958c22df0>
<MyProject.Fruit: 0x7fb958c22df0>

如您所见,输出与我想要的相同。现在我想知道这是否是模仿其输出的正确方法,或者我忽略了下面评论中提到的内容。

致谢:Matt、Martin R 和 Vacawama

使用String(self.hash, radix:16)。您可能需要自己添加 0x 前缀。

NSObject 的任何子class 继承 description NSObject 方法(在 NSObjectProtocol 中定义):

class Foo1 : NSObject { }
print(Foo1())
// <MyProject.Foo1: 0x100612fd0>

这个"default implementation"打印class名字和内存 对象的地址,例如参见 Friday Q&A 2013-01-25: Let's Build NSObject,其中显示了 Objective-C 的实现方式 可能看起来像:

- (NSString *)description
{
    return [NSString stringWithFormat: @"<%@: %p>", [self class], self];
}

%p格式将指针的值打印为十六进制数, 前面有 0x.

为了模仿 Swift,我们可以使用

  • String(reflecting: self.dynamicType) 其中 returns 作为字符串的完全限定 class 名称,以及
  • unsafeAddressOf(self) 其中 returns 指向存储的指针 对象的。

示例(使用方括号 [] 来证明 使用重写方法):

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]

这也适用于 "pure Swift classes",因为没有 Foundation 使用方法:

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]

注意(上面评论中已经提到),哈希值 对象的地址不一定与内存地址相同。 一个简单的例子是 NSArray() 其散列值只是数字 元素数:

let array = NSArray(objects: 1, 2, 3)
print(unsafeAddressOf(array)) // 0x00000001020011a0
print(array.hashValue) // 3

Swift3 的更新:

class Bar : CustomStringConvertible {
    var description : String {
        let className = String(reflecting: type(of: self))
        let address = Unmanaged.passUnretained(self).toOpaque()
        return "[\(className): \(address)]"
    }
}