【问题标题】:Fatal error when casting array of types to protocols: cannot be bridged from Objective-C将类型数组转换为协议时出现致命错误:无法从 Objective-C 桥接
【发布时间】:2016-04-02 23:35:36
【问题描述】:

那里有similar questions,但这是最新的 Swift 2.2 版本。希望现在有一个解决方案,因为在我看来这似乎是Protocol-Oriented Programming 的一大障碍。

以下分配给let results 失败并出现错误:Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0X0).

protocol P: class {
    var value:Int {get}
}

class X: P {
    var value = 0

    init(_ value:Int) {
        self.value = value
    }
}

func getItems() -> [P] {
    let items: [X] = [X(1), X(2), X(3)]
    return items
}

let results: [P] = getItems()

有什么方法可以将类数组视为它所遵循的协议数组?这似乎是对一种语言的一种非常简单和自然的要求,尤其是一种大量使用protocol-oriented 的语言。

我不想使用@objcflatMap,因为这对依赖链和性能有很大的影响——这将是一个hack。我希望它能够在本地工作,或者这是一个我们希望可以制定并呈现给 Apple / Swift 开源团队的错误。

【问题讨论】:

    标签: arrays swift swift2 protocols swift-protocols


    【解决方案1】:

    可能是我不明白你的问题,但这有效

    protocol P: class {
        var value:Int {get}
    }
    
    class X: P {
        var value = 0
    
        init(_ value:Int) {
            self.value = value
        }
    }
    
    func getItems() -> [P] {
        let items: [P] = [X(1), X(2), X(3)]
        return items
    }
    
    let results = getItems()
    results.forEach { (p) in
        print(p.value)
    }
    /*
     1
     2
     3
     */
    

    为什么将 [X] 转换为 [P] 不起作用?看下一个例子!

    protocol P: class {
        var value:Int {get}
    }
    protocol P1: class {
        var value: Double { get }
    }
    protocol Z {}
    class X: P,Z {
        var value = 0
    
        init(_ value:Int) {
            self.value = value
        }
    }
    class X1: P1,Z {
        var value = 0.0
    
        init(_ value:Double) {
            self.value = value
        }
    }
    
    func getItems() -> [Z] {
        // the only common type of all items is protocol Z  !!!!
        let items: [Z] = [X(1), X(2), X(3), X1(1), X1(2)]
        return items
    }
    
    let results = getItems()
    print(results.dynamicType)
    results.forEach { (p) in
        if let p = p as? P {
            print("P:", p.value)
        }
        if let p = p as? P1 {
            print("P1:", p.value)
        }
    }
    /*
     Array<Z>
     P: 1
     P: 2
     P: 3
     P1: 1.0
     P1: 2.0
    */
    

    这就是为什么使用 flatMap 是个好主意的原因,如果您想从结果中分离 X 和 X1 类型的项目

    let arrX = results.flatMap { $0 as? P }
    let arrX1 = results.flatMap { $0 as? P1 }
    print(arrX, arrX1) // [X, X, X] [X1, X1]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-18
      • 1970-01-01
      • 2015-07-18
      • 1970-01-01
      • 2015-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多