具有关联类型和可选方法的协议

时间:2018-03-11 03:59:26

标签: swift

我想用以下方法制作数据源协议:

  • 关联类型
  • 可选方法

例如(目前, Swift 4.1 编译以下代码被截获失败)

@objc protocol DataSourceNotWrkng {
    associatedtype Item

    var array: [Item] { get set }

    @objc optional func titleForHeader(in section: Int) -> String
}

class ComponentsDataSourceNotWrkng: DataSourceNotWrkng {
    typealias Item = Int

    var array: [Int]

    init(with array: [Int]) {
        self.array = array
    }
}

此代码失败且出现无法读取的错误:

0x0x7fdede80c9a0 Module name=tabbedApp
  0x0x7fdede1a8020 FileUnit file="/Users/gvr/Developer/freelance/tabbedApp (1.2)/tabbedApp/Utilities/DataSource.swift"
    0x0x7fdede1a83e0 ProtocolDecl name=DataSourceNotWrkng
      0x0x7fdede1a8a30 AbstractFunctionDecl name=_ : <<error type>>
(error_type)

1 个答案:

答案 0 :(得分:0)

您不能同时使用关联类型和Objective-C协议。具有相关类型的协议在Objective-C中不可见,而Objective-C协议不具有相关类型。

原因是关联类型是静态调度功能,而Objective-C协议依赖于运行时功能,因此它们无法在同一协议中共存。

编译器不应该允许你这样做,但似乎有一个错误,它会使它崩溃,然后才能给你一个正确的错误信息。

请注意,通过使用默认实现,可以通过除@objc协议之外的其他方式实现类似可选功能的功能。这将允许您继续使用协议及其相关类型:

protocol MyDataSource {
    associatedtype Item

    var array: [Item] { get set }

    // moved the optionality to the method result level
    func titleForHeader(in section: Int) -> String?
}

extension MyDataSource {
    // conforming types no longer need to implement this method,
    // if they don't want to, they will get the default implementation
    func titleForHeader(in section: Int) -> String? {
        return nil
    }
}