非对象类型的 NSCache 行为

NSCache behaviour with non-object types

下面的代码工作得很好,但我很惊讶,因为我认为 NSCache 需要对象键和值,而不需要 CGFloats。有人可以向我解释发生了什么吗?

class A
    var cachedPoints = NSCache()

    func rAt(theta theta: CGFloat) -> CGFloat {        
        if let r = self.cachedPoints.objectForKey(theta) as? CGFloat {
            return r
        }
        // do some very expensive maths here...
        let r = self.veryExpensiveFunction(theta)
        self.cachedPoints.setObject(r, forKey: theta)
        return r
    }
}

来自 Working with Cocoa Data Types 中 "Using Swift with Cocoa and Objective-C" 文档:

Numbers

Swift automatically bridges certain native number types, such as Int and Float, to NSNumber.
...
It also allows you to pass a value of type Int, for example, to an argument expecting an NSNumber.

文档提到 IntUIntFloatDoubleBool 作为自动桥接到 NSNumber 的类型,但显然 这也适用于 CGFloat(如果导入了 "Foundation")。 所以在

self.cachedPoints.setObject(r, forKey: theta)

rtheta 都被包装到 NSNumber 个实例中 然后传递给带有两个参数的 setObject() 方法 类型 AnyObject.

反方向也有桥接,不过就是 记录较少(或者我找不到)。你可以投一个 NSNumberCGFloat 的实例(或 IntFloat、...)

let num : NSNumber = ...
let x = num as CGFloat

并且结果与您在数字实例上调用 doubleValue(或 floatValue,具体取决于体系结构)相同。 在

let obj : AnyObject = ...
let y = obj as? CGFloat // CGFloat?

对象可以选择性地转换为 NSNumber 并且 – 如果成功 – 转换为 CGFloat,如上例所示。

这就是

中发生的事情
if let r = self.cachedPoints.objectForKey(theta) as? CGFloat { ... }

如果 objectForKey() 的 return 值是 NSNumber 那么 它被转换为 CGFloat 并分配给 r。除此以外, 可选绑定失败。