如何使用具有关联类型的协议数组定义协议

时间:2016-04-27 14:17:47

标签: swift

我正在尝试创建一个协议(AppStore),该协议要求conformer实现符合具有关联类型的协议(订阅者)的项目数组(订阅)。

目标 您可以将AppStore视为NSNotificationCenter。我想添加订阅者(比如addObserver ...)。当发生某些事情时,在订阅者上调用handleNewState(如handleNotification :)并传入实际上设置了一些变量的AppState构造函数。库存AppState没有任何可用的属性。

public protocol AppStore {
    //trying to have an array of subscriptions in the protocol
    //but a concrete Subscriber type needs to be specified, I thought a generic Subscriber would be more flexible here?
    var subscriptions:[Subscription<>]{get set}// Reference to generic type 'Subscription' requires arguments in <...>

    associatedtype AppStateType:AppState
    var appState:AppStateType { get set }
}
extension AppStore {
    //so that AppStore can implement this function
    public mutating func subscribe<T:protocol<Subscriber, AnyObject>>(aSubscriber:T){
        subscriptions.append(Subscription(sub:aSubscriber))
    }
}

public protocol Subscriber {
    associatedtype AppStateType
    func handleNewState(newState:AppStateType)
}

public struct Subscription <T:protocol<Subscriber, AnyObject>> {
    private weak var subscriber:T? = nil
    init(sub:T){
        self.subscriber = sub
    }
}
public protocol AppState { }

我应该如何定义var subscriptions:[Subscription<>]?或者我应该采用不同的方式

我会像这样使用它

public struct OSXAppState:AppState {
     var someStateProp:Int = 0
}
extension NSView : Subscriber { 
    public func handleNewState(newState:OSXAppState){
         if newState == 1 { //do this }
         else { //do that }
    } 
}
public struct OSXAppStore : AppStore {
    public typealias GenericSubscriber = NSView//???: something more generic "anything that implements Subscriber"
    public var subscriptions: [Subscription<GenericSubscriber>] = []
    public var appState: AppState = OSXAppState()
}

1 个答案:

答案 0 :(得分:1)

我认为你坚持使用AnyObject才能使用weak。这可以通过使协议仅限类来更简单地完成。我改变了协议组成

protocol<Subscriber, AnyObject>

protocol Subscriber: class

我还添加了

associatedtype GenericSubscriber: SubscriberType

允许通用

Subscription<T: SubscriberType>

在数组中使用。

public protocol Subscriber: class {
  associatedtype AppStateType:AppState
  func handleNewState(newState:AppStateType)
}

public struct Subscription<T:Subscriber> {
  private weak var subscriber:T?
  init(sub:T){
    self.subscriber = sub
  }
}

public protocol AppState { }

public protocol AppStore {
  // Allows Subscription<T:Subscriber> to be used as an array element
  associatedtype GenericSubscriber:Subscriber

  var subscriptions:[Subscription<GenericSubscriber>]{get set}
  var appState:AppState { get set }
}

extension AppStore {
  // The concrete type of GenericSubscriber is inferred from this context
  public mutating func subscribe(aSubscriber: GenericSubscriber){
    subscriptions.append(Subscription<GenericSubscriber>(sub:aSubscriber))
  }
}

public struct OSXAppState:AppState {
  var someStateProp:Int
}
extension NSView : Subscriber {
  public func handleNewState(newState:OSXAppState){
  }
}