CFDictionary не будет соединяться с NSDictionary (Swift 2.0 / iOS9)
Хорошо, это тот случай, с которым я столкнулся при работе с 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)
1 ответ
Кажется, причина в том, что функция возвращает необязательныйCFDictionary?
и это не может быть приведено к (не обязательно)NSDictionary
,
Вот более простой пример, демонстрирующий ту же проблему с CFString
против 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)
соединяет стремительную струну с 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
}