有一个协议:
protocol Valuable {
func value() -> Int
}
和实现协议的类:
class Value: Valuable {
private let v: Int
init(value: Int) {
v = value
}
func value() -> Int {
return v
}
}
有一个Value对象数组存储在Any类型的变量中:
let any: Any = [Value(value: 1), Value(value: 2), Value(value: 3)]
可以将Any转换为[Value]:
let arrayOfValue = any as? [Value] // [1, 2, 3]
为什么不能将Any设为[Valuable]?
let arrayOfValuable = any as! [Valuable] // compiler error BAD INSTRUCTION
let arrayOfValuable2 = any as? [Valuable] // nil
答案 0 :(得分:6)
更新:在Swift3中,完全可以将[Any]
投射到[Valuable]
。只要阵列中的所有元素都可以投射,演员阵容就会成功;否则演员会失败。
var strings: [Any] = ["cadena"]
var mixed: [Any] = ["cadena", 12]
strings as! [String] // ["cadena"]
mixed as? [String] // nil
mixed as! [String] // Error! Could not cast value...
以前从Swift 2开始:要从[Valuable]
中制作[Any]
,必须使用map
之类的功能手动完成,其他答案已解释过。
目前Swift中没有covariance nor contravariance泛型(从Swift 2开始)。这意味着不同类型的数组(如[String]
或[UIView]
)不能相互转换,也不能比较它们的类型。
[UIView]
是[UIButton]
的子类, UIButton
和UIView
之间都不存在层次结构。这就是为什么即使以下内容返回true:
Valuable.self is Any.Type // true
由于同样的原因,以下演员表会产生错误:
var anyArray: [Any] = ["cadena"]
anyArray as! [String] // BAD_INSTRUCTION error
"some string" as! Double // BAD_INSTRUCTION error
这两个条款没有任何关系,并且演员阵容是不可能的,因为as!
是强迫演员,它会引发错误。
答案 1 :(得分:3)
我做了一些挖掘,你必须添加@objc属性如下
@objc
protocol Valuable {
func value() -> Int
}
class Value: Valuable {
private let v: Int
init(value: Int) {
v = value
}
@objc func value() -> Int {
return v
}
}
let any: AnyObject = [Value(value: 1), Value(value: 2), Value(value: 3)]
let arrayOfValueable = any as! [Valuable] // [{v 1}, {v 2}, {v 3}]
有关更多信息并获取“为什么?”的答案:https://stackoverflow.com/a/25589323/989631
希望这会对你有所帮助。
另外,只有在使用AnyObject而不是Any:(
答案 2 :(得分:2)
它对我有用:
let arrayOfValuable = arrayOfValue?.map { $0 as Valuable }
或相同:
let arrayOfValuable2 = (any as? [Value])?.map { $0 as Valuable }
总之,arrayOfValuable
的类型应为[Valuable]?
修改强>
或试试这个:
let arrayOfAny: [Any] = [Value(value: 1), Value(value: 2), Value(value: 3)]
let arrayOfValuable3 = arrayOfAny.map { $0 as Valuable }
当然,更好的方法是将arrayOfAny
声明为[Valuable]
,这样您就不会遇到任何问题。
答案 3 :(得分:0)
let arrayOfAny:Array<Any> = [1,"2",3.0,CGFloat(4)]
let stringArray:Array<String> = arrayOfAny.map {String($0)}
print(stringArray)//"1", "2", "3.0","4.0"
<强>结论:强>
有时它可以从一种数组类型转换为另一种数组类型。在大多数情况下,最好的方法是不转换数组类型,而是在打包数组之前进行实例检查或在解压缩数组后进行实例检查