Swift:向协议对象数组强制转换任何
有一个协议:Swift:向协议对象数组强制转换任何,swift,casting,protocols,Swift,Casting,Protocols,有一个协议: protocol Valuable { func value() -> Int } class Value: Valuable { private let v: Int init(value: Int) { v = value } func value() -> Int { return v } } 以及一个实现该协议的类: protocol Valuable { func
protocol Valuable {
func value() -> Int
}
class Value: Valuable {
private let v: Int
init(value: Int) {
v = value
}
func value() -> Int {
return v
}
}
以及一个实现该协议的类:
protocol Valuable {
func value() -> Int
}
class Value: Valuable {
private let v: Int
init(value: Int) {
v = value
}
func value() -> Int {
return v
}
}
任何类型的变量中都存储有一个值对象数组:
let any: Any = [Value(value: 1), Value(value: 2), Value(value: 3)]
可以将任何值转换为[值]:
let arrayOfValue = any as? [Value] // [1, 2, 3]
为什么不可能对[有价值的]进行案例分析
let arrayOfValuable = any as! [Valuable] // compiler error BAD INSTRUCTION
let arrayOfValuable2 = any as? [Valuable] // nil
这对我很有用:
let arrayOfValuable = arrayOfValue?.map { $0 as Valuable }
或相同:
let arrayOfValuable2 = (any as? [Value])?.map { $0 as Valuable }
总之,arrayOfValuable
的类型应为[valued]?
编辑:
或者试试这个:
let arrayOfAny: [Any] = [Value(value: 1), Value(value: 2), Value(value: 3)]
let arrayOfValuable3 = arrayOfAny.map { $0 as Valuable }
当然,更好的方法是将
arrayOfAny
声明为[valuely]
,这样以后就不会有问题了。我做了一些挖掘,您必须添加@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}]
欲了解更多信息并获取“为什么?”,请执行以下操作:
希望这对你有帮助
编辑
另外,只有使用AnyObject而不是Any:(更新:在Swift3中,完全可以将
[Any]
强制转换为[valuely]
。只要可以强制转换数组中的所有元素,强制转换就会成功;否则,强制转换将失败
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开始:要从
[任何]
中生成[有价值的]
,必须使用map
等功能手动完成,如其他答案所述
目前,Swift中没有泛型。这意味着不同类型的数组,如[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!
是强制转换,它会导致错误。将数组[Any]强制转换为数组[String]
let arrayOfAny:Array=[1,“2”,3.0,CGFloat(4)]
让stringArray:Array=arrayOfAny.map{String($0)}
打印(字符串数组)/“1”、“2”、“3.0”、“4.0”
结论:有时从一种数组类型转换为另一种数组类型很有用。在大多数情况下,最好的方法不是转换数组类型,而是在打包数组之前进行实例检查,或者在解压缩数组之后进行实例检查e cast不起作用,但可能首先将其声明为
[有价值]
就足以作为您的解决方案:让任何:[有价值]=[值(值:1)、值(值:2)、值(值:3)]
这不一样-你在第二张地图中投的是值,而不是值
,这就是问题所要问的。用as?[Value]
替换as?[Value]
,你会得到零
,正如OP所说的那样…@Grimxn我在看到实际答案后明白了。