【发布时间】:2016-03-03 14:53:19
【问题描述】:
我在 as? 处遇到编译器错误。类型“Type”不符合协议“AnyObject”。为什么会这样?需要 AnyObject 吗?
func listForKey<Type>(key: String) -> [Type] {
guard let fullList = (itemList as NSArray).valueForKey( key ) as? NSArray else {
return [Type]()
}
// Filter out any values not matching the expected type such as if nil was used (value wasn't supplied)!
let typeOnlyList = fullList.filter( {$0 as? Type != nil} )
guard let foundList = typeOnlyList as? [Type] else { // <== at as?, Compiler Error 'Type' does not conform to protocol AnyObject
return [Type]()
}
return foundList
}
如果我将声明更改为以下内容,它将编译:
func listForKey<Type:AnyObject>(key: String) -> [Type] {
但是,它不能与 String 对象一起使用,因为 String 的类型是 any。有什么想法吗?
在阅读 Anton 的评论后,我认为我有一个潜在的解决方案。这解决了编译时错误,但现在我得到一个运行时错误(致命错误:数组无法从 Objective-C 桥接):
extension NSArray {
public func toSwiftArray<Type>() -> [Type] {
// Filter out any values not matching the expected type such as nil
let typeOnlyList : [AnyObject] = self.filter( {$0 is Type} )
let typeOnlyAnyList : [Any] = typeOnlyList as [Any] // <== Runtime error EXC_BAD_INSTRUCTION
guard let foundList : [Type] = typeOnlyAnyList as? [Type] else {
return [Type]()
}
return foundList
}
}
为什么从 [AnyObject] 转换为 [Any] 会导致运行时错误?我认为 [Any] 是 [AnyObject] 的超集。
【问题讨论】:
-
尝试使用 is 关键字 - 例如在过滤器中传递的闭包中放入 {$0 is Type} 我也建议对泛型类型使用单个大写字母,因为这是约定
-
我将它切换到 {$0 is String} 因为它更清楚,但问题出在下一行。它在抱怨 as?在下一行
-
这不会总是通过,因为 [Type] 不能是 nil,但你说 nil 是一个选项
-
好问题:底层对象有 swift 选项作为成员。因此,NSArray 中很可能包含 NIL 占位符对象。这些占位符对象无法转换为 Type,因为它们是 nil。所以过滤器确保在最终结果中只包含可以转换为类型的对象。因此允许我们从 NSArray 中返回一个有效的 swift [Type]。
-
我相信这可能与
as?是动态转换和动态转换只能在类上使用这一事实有关,因为结构不能使用继承(你不能在不同的结构类型之间进行转换)。AnyObject是 swift 中类类型的表示。