2015-09-22 20 views
5

OK, đây là trường hợp tôi gặp phải khi làm việc với CGImageSource và nhận thấy rằng cầu nối miễn phí giữa CFDictionary và NSDictionary dường như gặp sự cố trong một số trường hợp . Tôi đã quản lý để xây dựng ví dụ dưới đây để cho thấy ý tôi là:CFDictionary sẽ không kết nối với NSDictionary (Swift 2.0/iOS9)

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 
} 

Khá đơn giản (và hơi ngớ ngẩn) nhưng hàm của nó trở về và tùy chọn CFDictionary. "Vui vẻ" bắt đầu khi cố gắng tạo NSDictionary từ chức năng này:

Tại sao công việc sau đây không?

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

Mặc dù điều này có hiệu quả?

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

XCode 7.0 (7A220)

Trả lời

5

Lý do dường như là hàm trả về một tùy chọn CFDictionary? và rằng không thể được đúc để một (không bắt buộc) NSDictionary.

Dưới đây là một ví dụ đơn giản thể hiện cùng một vấn đề với CFString vs NSString:

let cfString = "foobar" as CFString? 

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

(Câu hỏi đặt ra vẫn là lý do tại sao điều này không đưa ra một lỗi biên dịch hoặc ít nhất một cảnh báo trình biên dịch vì dàn diễn viên không bắt buộc này có thể không bao giờ thành công)

Nhưng một đúc đến một tùy chọn NSString? công trình:.

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

Trong trường hợp của bạn, nếu bạn thay đổi "trường hợp có vấn đề" để

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

sau đó khối if-được thực thi.


Lưu ý rằng phương pháp của mình để xây dựng một CFDictionary trong Swift là không đúng và thực sự gây ra tai nạn trong chương trình thử nghiệm của tôi. Một lý do là các cuộc gọi lại từ điển được đặt thành cấu trúc trống. Một vấn đề khác là unsafeAddressOf(key) sẽ gửi chuỗi Swift tới số NSString có thể được deallocated ngay lập tức.

Tôi không biết những gì các phương pháp tốt nhất là xây dựng một CFDictionary trong Swift, nhưng điều này làm việc trong thử nghiệm của tôi:

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 
} 
+0

Nó không trả lời cho câu hỏi - làm thế nào để chuyển đổi sang NSDictionary. –

+0

@AlexanderVolkov: Tôi nghĩ rằng nó có: 'nếu để cho problemDictionary = cfDict là NSDictionary? {...} 'phôi CFDictionary? để NSDictionary ?, và sử dụng tùy chọn ràng buộc để unwrap rằng để NSDictionary. Vui lòng cho tôi biết bạn thiếu thông tin nào. –

+0

Hãy xem ảnh chụp màn hình. Kết quả của dàn diễn viên là nil - http://www.screencast.com/t/hbjhDzCs0K –

Các vấn đề liên quan