2016-01-21 28 views
15

在Swift中,AnyObject如何支持下标,即使对于不可订阅的类型?例如:Swift AnyObject的下标,它是从哪里来的?

let numbers: AnyObject = [11, 22, 33] 
numbers[0]  // returns 11 

let prices: AnyObject = ["Bread": 3.49, "Pencil": 0.5] 
prices["Bread"] // returns 3.49 

let number: AnyObject = 5 
number[0]  // return nil 

let number: AnyObject = Int(5) 
number[0]  // return nil 

然而,如果我number声明为Int那么它是一个语法错误:

let number: Int = 5 
number[0]  // won't compile 

有趣的是,Any没有标支持。

+0

相关:http://stackoverflow.com/questions/24154304/why-is-an-array-an-anyobject-in-swift – dfri

+0

的问题是非常有趣的了解幕后的事情,但相当理论。在实践中,你不会使用类型注释'AnyObject'作为编译器可以推断的正确类型的对象,而且你 - 开发人员 - 确切地知道。无论如何,Apple强烈建议不要使用(这样的)类型的注释。 – vadian

+1

'NSJSONSerialization.JSONObjectWithData'返回'AnyObject' –

回答

5

它具有AnyObject类型的对象赋值的时候做的类型的桥接:

let numbers: AnyObject = [11, 22, 33] 
print(numbers.dynamicType) // _SwiftDeferredNSArray.Type 

let prices: AnyObject = ["Bread": 3.49, "Pencil": 0.5] 
print(prices.dynamicType) // _NativeDictionaryStorageOwner<String, Double>.Type 

let number: AnyObject = 5 
print(number.dynamicType) // __NSCFNumber.Type 

let anotherNumber: Int = 5 
print(anotherNumber.dynamicType) // Int.Type 

在幕后,_SwiftDeferredNSArray.Type_NativeDictionaryStorageOwner<String, Double>.Type,虽然Int.Type__NSCFNumber.Type必须支持标。

这是假设你已经导入了基金会。有关纯Swift类型的解释,请参见Cristik's answer

12

这只有在您导入Foundation时才有效,因为Swift在这种情况下会执行一些桥接到Objective-C类型 - 类似于NSArray的对象。

import Foundation 

let numbers: AnyObject = [11, 22, 33] 
numbers.dynamicType //_SwiftDeferredNSArray.Type 

如果不导入Foundation,那么你甚至不能进行分配(因为斯威夫特阵列是一个结构,而不是一个对象)。

let numbers: AnyObject = [11, 22, 33] // error: contextual type 'AnyObject' cannot be used with array literal 

可以转换为Any,虽然:

let numbers: Any = [11, 22, 33]  
numbers.dynamicType // Array<Int>.Type 

为什么会出现import Foundation的伎俩?这是记录在AnyObject类型描述:

/// When used as a concrete type, all known `@objc` methods and 
/// properties are available, as implicitly-unwrapped-optional methods 
/// and properties respectively, on each instance of `AnyObject`. For 
/// example: 
/// 
///  class C { 
///  @objc func getCValue() -> Int { return 42 } 
///  } 
/// 
///  // If x has a method @objc getValue()->Int, call it and 
///  // return the result. Otherwise, return nil. 

这意味着,你甚至可以打电话给你的阵列上的方法不一定对NSArray存在,但存在于Objective-C世界,例如像:

numbers.lowercaseString  // nil 

和Swift将优雅地返回给您一个nil值,而不是抛出一个令人讨厌的object does not recognises selector异常,就像在Objective-C中发生的那样。如果这是好还是坏,还有待讨论上述:)

更新 似乎只能用于性质的工作,以及与财产等的方法,如果你尝试使用Objective-C的方法,那么你会碰上了无法识别的选择问题:

import Foundation 

@objc class TestClass: NSObject { 
    @objc var someProperty: Int = 20 
    @objc func someMethod() {} 
} 

let numbers: AnyObject = [11, 22, 33] 
numbers.lowercaseString    // nil 
numbers.someMethod      // nil 
numbers.someMethod()     // unrecognized selector 
numbers.stringByAppendingString("abc") // unrecognized selector 
+0

伟大的发现和一个很好的答案。我的答案假定基金会已经进口。感谢您提供纯粹的Swift解释! – JAL