我在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] {
然而,由于字符串类型为any,因此它不能使用String对象。关于发生了什么的任何想法?
我认为在阅读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]的超级集合。
答案 0 :(得分:1)
下面:
guard let fullList = ... as? NSArray
...您声明fullList
变量为NSArray
。
因此typeOnlyList
也是NSArray
(这是对fullList
进行过滤的结果。)
NSArray
的元素是AnyObject
(从Objective-C桥接)。
因此,当您尝试强制转换typeOnlyList as? [Type]
时,Swift希望Type
符合AnyObject
协议。
答案 1 :(得分:0)
我想这并没有真正回答原来的问题。但是,这是一种可以完成工作的解决方法。我仍然不明白为什么上面的解决方案不起作用(特别是从[AnyObject]转换为[Any]时的致命错误),但我采用了一种不同的方法,这种方法很有用:
extension NSArray {
public func toSwiftArray<Type>() -> [Type] {
var swiftArray = [Type]()
for value in self {
if let valueOfType = value as? Type {
swiftArray.append( valueOfType )
}
}
return swiftArray
}
public func toSwiftArray<Type>() -> ([Type], [Any]) {
var swiftTypeArray = [Type]()
var unknownTypeArray = [Any]()
for value in self {
if let valueOfType = value as? Type {
swiftTypeArray.append( valueOfType )
} else {
unknownTypeArray.append( value )
}
}
return (swiftTypeArray, unknownTypeArray)
}
}
不确定为什么我不能使用.filter来执行此操作,但这是一个非常简单的问题解决方案,它还允许返回无法转换的值列表的版本。这是转换为具有完全类型安全性的NSArray的非常方便的例程。
答案 2 :(得分:0)
如果您想在Swift中使用NSArray
,则必须仅使用类,因为NSArray
无法保留其他任何内容。
extension NSArray {
public func toSwiftArray<Type: AnyObject>() -> [Type] {
let typeOnlyList : NSArray = self.filter( {$0 is Type} )
return typeOnlyList as! Array<Type>
}
}
let nsArray: NSArray = [10, 20, "my-text"]
print("NSArray: \(nsArray)")
let swiftArray: [NSString] = nsArray.toSwiftArray()
print("Swift array: \(swiftArray)")
简而言之:使用NSString
代替String
。您也可以将[NSString]
转换为[String]
作为第二步。