Swift:type String不符合协议AnyObject

时间:2014-10-02 21:20:43

标签: swift ios8 nsdictionary

我可能错过了一些基本的东西。无法从NSDictionary值中获取数组。

代码是:

import Foundation

//need to add Settings bundle to project in order to run this test.
class CompileError {

    func foo(){
        let path = NSBundle.mainBundle().pathForResource("Settings", ofType: "bundle");
        if(path == nil) {
            NSLog("Could not find Settings.bundle");
            return;
        }

        let settings:NSDictionary = NSDictionary(contentsOfFile:path!.stringByAppendingPathComponent("Root.plist"));
        var preferences:Array = settings.objectForKey("PreferenceSpecifiers") as Array //Get Compile Error: type String doesn't conform to protocol AnyObject  
    }
}

在调试器中看到,Preferences对象有一个用于键" PreferenceSpecifiers"的数组,但我无法施放它。 如果我尝试:

var preferences:Array = settings.objectForKey("PreferenceSpecifiers")?.Array 

它编译但是首选项对象设置为nil。

2 个答案:

答案 0 :(得分:4)

虽然很有趣,但我担心你的答案并不能解决你的问题。转换为NSArray“工作”的原因是因为NSArray没有关联的类型,而Swift的Array会这样做。 Array struct 的相关摘要如下:

struct Array<T> : MutableCollectionType {
    typealias Element = T
    init<S : SequenceType>(s: S)
    // and much more – just Command-click on `Array` and check it out for yourself

显然,Array是一个通用的struct集合,即只有当Element s(或T s)的类型已知时,才会完全指定其类型。所以as NSArray并不是“正确的指令”,因为它推迟了掌握仿制药所需的时间。然而,这应该是愉快和有益的,因为作为一种语言,斯威夫特是新的,并且正在蓬勃发展非常古老和经验丰富,继承了许多其他语言的所有好东西... < / p>

简而言之:

let arr: NSArray = [1,2,3,4,5]         
// even after casting to `NSArray`, `arr` is still an `[AnyObject]`
//     e.g. try this:

// arr is [AnyObject]                  // compiler error: 'is' test is always true

let ints = arr as [Int]                // --> [1,2,3,4,5]

// or more safely:

if let ints = arr as? [Int] {
    ints                               // --> [1,2,3,4,5]
}

更贴近您的情况:

let array: NSArray = ["settings", "etc", "..."] // just simulating the objects you are working with

let settings: NSDictionary = ["PreferenceSpecifiers": array] // ditto

if let prefs = settings["PreferenceSpecifiers"] as? [String] {
    prefs                              // --> ["settings", "etc", "..."]
    // this is only if *all* PreferenceSpecifiers are NSStrings, 
    //     otherwise, you'll have to downcast them as an when you access them
    //     rather than wholesale, as I did here...
} else {
    // ouch, no preferences found
}

来自同一项目中的 Swift和Objective-C (文档):

  

<强>阵列

     

Swift自动在Array类型和NSArray之间架起桥梁   类。当您从NSArray对象桥接到Swift数组时,   结果数组的类型为[AnyObject]。对象是AnyObject   如果它是Objective-C或Swift类的实例,则兼容,或者   如果对象可以桥接到一个。您可以桥接任何NSArray对象   到Swift数组,因为所有Objective-C对象都是AnyObject   兼容。因为所有NSArray对象都可以桥接到Swift   数组,Swift编译器用[AnyObject]替换NSArray类   何时导入Objective-C API。

     

将NSArray对象桥接到Swift数组后,您也可以   将数组转换为更具体的类型。与铸造不同   NSArray类为[AnyObject]类型,从AnyObject向下转换为   更具体的类型不能保证成功。编译器不能   直到运行时才知道数组中的所有元素   可以下载到您指定的类型。结果,向下倾斜   从[AnyObject]到[SomeType]返回一个可选值。例如,   如果你知道Swift数组只包含UIView的实例   class(或UIView类的子类),您可以向下转换数组   AnyObject类型元素到UIView对象的数组。如果有的话   Swift数组中的元素在运行时实际上不是UIView对象,   演员回归无。

     

<强>字典

     

除了数组之外,Swift还自动桥接了   字典类型和NSDictionary类。当你从一个桥​​梁   NSDictionary对象是一个Swift字典,结果字典是   类型为[NSObject:AnyObject]。您可以桥接任何NSDictionary对象   到Swift字典,因为所有Objective-C对象都是AnyObject   兼容。回想一下,如果一个对象是AnyObject兼容的   Objective-C或Swift类的实例,或者它是否可以桥接到   一。所有NSDictionary对象都可以桥接到Swift词典,所以   Swift编译器用[NSObject:替换NSDictionary类:   AnyObject]在导入Objective-C API时。

答案 1 :(得分:1)

发现了。假设Array与NSArray相同,并且它不是。

正确的说明是:

var preferences = settings.objectForKey("PreferenceSpecifiers") as NSArray