我的目标是编写一些可以将[AnyObject]
转换为Result<[SomeObject], NSError>
的内容,以便在使用混合的Swift / Obj-C代码库时轻松进行安全和可链接的转换。条件转发运算符as?
似乎支持这一点,但是我无法获得利用该行为的通用函数。我已经简化了我遇到的问题:
class A { }
let obj = A()
let array: [AnyObject] = [obj]
func cast<T, U>(x: T, type: U.Type) -> U? {
if let x = x as? U {
return x
} else {
return nil
}
}
// This works
if let array = array as? [A] {
println(array)
}
// This works
println(cast(obj, A.self))
// This doesn't
println(cast(array, [A].self))
答案 0 :(得分:2)
注意:这适用于Swift 2.0,我不知道1.2,试试看
如果您想要执行此类操作,则必须使用cast
方法重载SequenceType
方法:
func cast<T : SequenceType, U : SequenceType>(x: T, type: U.Type) -> [U.Generator.Element]? {
let y = x.map{ $0 as? U.Generator.Element }
if y.contains({ $0 == nil }) {
return nil
} else {
return y.flatMap{ $0 } // Swift 1.2 : y.map{ $0! }
}
}
编辑:根据你的编辑改变
答案 1 :(得分:1)
通常情况下,即使GenericType<A> as? GenericType<B>
是B
的子类型,Swift也不支持A
强制转换。 Array<A> as? Array<B>
只是为了方便我们。
有一个未记录的内部内置函数:
func _arrayConditionalDownCastElements<SourceElement, TargetElement>(a: Array<SourceElement>) -> [TargetElement]?
根据我的假设,当我们执行someArray as? [B]
时,Swift会隐式调用此函数。但是,使用泛型类型,就像你的情况一样,Swift编译器不能将它绑定到_arrayConditionalDownCastElements
,因为它在编译时是不可预测的。
无论如何,您可以手动调用它,并将cast
实现为重载函数:
func cast<T,U>(x:T, _: U.Type) -> U? {
return x as? U
}
func cast<T,U>(x:[T], _: [U].Type) -> [U]? {
return _arrayConditionalCast(x)
}
同样,_dictionaryDownCastConditional
有Dictionary
,_setDownCastConditional
有Set
:
func _dictionaryDownCastConditional<BaseKey, BaseValue, DerivedKey, DerivedValue>(source: Dictionary<BaseKey, BaseValue>) -> Dictionary<DerivedKey, DerivedValue>?
func _setDownCastConditional<BaseValue, DerivedValue>(source: Set<BaseValue>) -> Set<DerivedValue>?
使用此:
func cast<TKey,TValue, UKey, UValue>(x:[TKey: TValue], _: [UKey:UValue].Type) -> [UKey: UValue]? {
return _dictionaryDownCastConditional(x)
}
func cast<T, U>(x: Set<T>, _: Set<U>.Type) -> Set<U>? {
return _setDownCastConditional(x)
}
同样,他们无证件。使用它们需要您自担风险:)