将[AnyObject]转换为可能是也可能不是集合类型的泛型类型

时间:2016-03-21 11:52:17

标签: swift generics casting

我有一个AnyObject数组,我想把它(或其对象的一个​​)转换为通用类型T,它可能是也可能不是一个数组。

我的第一次尝试:

class MyClass<T> {

    func someMethod() -> T? {

        let anyObjectArray: [AnyObject] = // ... array obtained from Objective-C framework

        if let objectsAsCollection = anyObjectArray as? T {  // Cast always fails
            return objectsAsCollection
        } else if let firstObject = anyObjectArray.first as? T {
            return firstObject
        } else {
            return nil
        }
    }
}

if letT(例如Array)时,第一次T.self == Array<SomeObject>.self投射会失败。

我会尝试这样的事情,但它涉及以某种方式引入另一个泛型参数,因此无效如下所示:

extension MyClass where T == Array<U> {

    fun someMethod() -> T? {

        let anyObjectArray: [AnyObject] = // ... array obtained from Objective-C framework

        if let objectsAsCollection = anyObjectArray.flatMap({ $0 as? U }) {
            return objectsAsCollection
        } else if let firstObject = anyObjectArray.first as? T {
            return firstObject
        } else {
            return nil
        }
    }
}

想要这样做的原因是我使用Objective-C框架(RestKit)从REST API获取结果。我正在Swift中构建一个顶层,它根据所做的请求将这些结果作为特定类型传回,所以我有Result类型看起来像这样:

enum Result<T>: {
    case Success(T)
    case Failure(Error)
}

有时候T是一个单独的对象,有时它是一个对象数组,但Objective-C框架总是将结果作为数组返回。

1 个答案:

答案 0 :(得分:3)

以下语法将起作用:

class MyClass<T> {
    func someMethod() -> T? {
        // let's not convert to [AnyObject] here, keep it as NSArray
        let anyObjectArray: NSArray = ...

        // For some reason conversion from [AnyObject] to [T] fails...
        // However, conversion from NSArray is special
        if let objectsAsCollection = anyObjectArray as? T {
            return objectsAsCollection
        } else if let firstObject = (anyObjectArray as [AnyObject]).first as? T {
            return firstObject
        } else {
            return nil
        }
    }
}

但是,这只是一个可能的错误的解决方法。我们可以将问题归结为以下几点:

class GenericClass<T> {
    func someMethod() {
        let anyObjectArray: [AnyObject] = ["test1", "test2", "test3"]

        print(T) //Array<String>
        print(T.self == Array<String>.self) //true

        print(anyObjectArray is [String]) //true
        print(anyObjectArray is T) //false - BUG
    }
}

let instance = GenericClass<[String]>()
instance.someMethod()

(报告:SR-1054

对我来说这看起来像一个明显的错误。它实际上看起来像Type of optionals cannot be inferred correctly in swift 2.2

中讨论的bug的另一个实例