简体   繁体   English

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

[英]Protocols with associated type and optional methods

I would like to make a data source protocol with: 我想做一个数据源协议:

  • Associated type 关联类型
  • Optional method 可选方法

eg(currently, with Swift 4.1 compilation for code snipped below fails) 例如(当前,使用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
    }
}

This code fails with unreadable error: 此代码失败,并出现无法读取的错误:

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)

You can't use both associated types and Objective-C protocols. 您不能同时使用关联的类型和Objective-C协议。 Protocol with associated types are not visible into Objective-C, and Objective-C protocols can't have associated types. 具有关联类型的协议在Objective-C中不可见,并且Objective-C协议不能具有关联类型。

The reason is associated types is a static dispatch feature, while Objective-C protocol rely on runtime features, so they can't live together in the same protocol. 原因是关联的类型是静态调度功能,而Objective-C协议依赖于运行时功能,因此它们不能在同一协议中一起使用。

The compiler should not allow you to do this, however seems there's a bug that makes it crash it before it can give you a proper error message. 编译器不应允许您执行此操作,但是似乎有一个错误使它崩溃,然后才能给您适当的错误消息。

Note that a feature like an optional function can be achieved by other means than an @objc protocol, by using default implementations. 请注意,可以使用默认实现,通过@objc协议以外的其他方式来实现诸如可选功能之类的功能。 This will allow you to keep using the protocol and it's associated type: 这将允许您继续使用该协议及其关联的类型:

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
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM