5

好的,这是我在使用 CGImageSource 时遇到的一个案例,并注意到 CFDictionary 和 NSDictionary 之间的免费桥接在某些情况下似乎遇到了问题。我设法构建了以下示例来说明我的意思:

func optionalProblemDictionary() -> CFDictionary? {
    let key = "key"
    let value = "value"
    var keyCallBacks = CFDictionaryKeyCallBacks()
    var valueCallBacks = CFDictionaryValueCallBacks()

    let cfDictionary = CFDictionaryCreate(kCFAllocatorDefault, UnsafeMutablePointer(unsafeAddressOf(key)), UnsafeMutablePointer(unsafeAddressOf(value)), 1, &keyCallBacks, &valueCallBacks)
    return cfDictionary
}

相当简单(也有点傻),但它是一个返回函数和可选的 CFDictionary。当试图从这个函数创建一个 NSDictionary 时,“乐趣”就开始了:

为什么以下不起作用?

if let problemDictionary = optionalProblemDictionary() as? NSDictionary {
    print(problemDictionary) // never enters, no warnings, compiles just fine
}

虽然这工作正常?

if let cfDictionary = optionalProblemDictionary() {
    let problemDictionary = cfDictionary as NSDictionary
    print(problemDictionary)
}

XCode 7.0 (7A220)

4

1 回答 1

5

原因似乎是该函数返回一个可选 CFDictionary?的并且不能强制转换为 (non-optional) NSDictionary

这是一个更简单的示例,演示了与CFStringvs相同的问题NSString

let cfString = "foobar" as CFString?

if let s1 = cfString as? NSString {
    print("s1 = \(s1)") // not executed
}

(问题仍然是为什么这不会给出编译器错误或至少是编译器警告,因为这种可选转换 永远不会成功。)

但是转换为可选的NSString?作品:

if let s2 = cfString as NSString? {
    print("s2 = \(s2)") // prints "s2 = foobar"
}

在您的情况下,如果您将“有问题的情况”更改为

if let problemDictionary = cfDict as NSDictionary? {
    print(problemDictionary)
}

然后执行 if 块。


请注意,您CFDictionary在 Swift 中构建的方法不正确,实际上在我的测试中导致程序崩溃。一个原因是字典回调设置为空结构。另一个问题是unsafeAddressOf(key)将 Swift 字符串连接到NSString可以立即释放的字符串。

我不知道CFDictionary在 Swift 中构建 a 的最佳方法是什么,但这在我的测试中有效:

func optionalProblemDictionary() -> CFDictionary? {

    let key = "key" as NSString 
    let value = "value" as NSString

    var keys = [ unsafeAddressOf(key) ]
    var values = [ unsafeAddressOf(value) ]

    var keyCallBacks = kCFTypeDictionaryKeyCallBacks
    var valueCallBacks = kCFTypeDictionaryValueCallBacks

    let cfDictionary = CFDictionaryCreate(kCFAllocatorDefault, &keys, &values, 1, &keyCallBacks, &valueCallBacks)
    return cfDictionary
}
于 2015-09-22T16:58:23.233 回答