CFDictionary不会桥接到NSDictionary(Swift 2.0/iOS9)

T. *_*sen 5 nsdictionary toll-free-bridging swift cfdictionary swift2

好吧,这是我在使用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
}
Run Code Online (Sandbox Code Playgroud)

相当简单(有点傻)但它的功能返回和可选的CFDictionary.尝试从此函数创建NSDictionary时,"fun"开始:

以下为什么不工作?

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

虽然这很好吗?

if let cfDictionary = optionalProblemDictionary() {
    let problemDictionary = cfDictionary as NSDictionary
    print(problemDictionary)
}
Run Code Online (Sandbox Code Playgroud)

XCode 7.0(7A220)

Mar*_*n R 5

原因似乎是函数返回一个可选的 CFDictionary?,并且不能转换为(非可选) NSDictionary.

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

let cfString = "foobar" as CFString?

if let s1 = cfString as? NSString {
    print("s1 = \(s1)") // not executed
}
Run Code Online (Sandbox Code Playgroud)

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

但是对可选NSString?作品的投射:

if let s2 = cfString as NSString? {
    print("s2 = \(s2)") // prints "s2 = foobar"
}
Run Code Online (Sandbox Code Playgroud)

在您的情况下,如果您将"有问题的案例"更改为

if let problemDictionary = cfDict as NSDictionary? {
    print(problemDictionary)
}
Run Code Online (Sandbox Code Playgroud)

然后执行if-block.


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

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

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
}
Run Code Online (Sandbox Code Playgroud)