2016-04-27 2 views
0

Я пытаюсь создать протокол (AppStore), который требует, чтобы конформер реализовал массив элементов (подписки), соответствующих протоколу (подписчику), который имеет связанный тип.Как определить протокол с массивом протокола с ассоциированным типом

цель Вы можете думать о 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

Опишите больше о вашей цели. Какую проблему вы пытаетесь решить с помощью этого кода? Это может быть не самый прямой путь к этой цели. – ColGraff

ответ

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){ 
    } 
} 
+0

«ассоциированный тип AppStateType» является ключевым элементом здесь. Я хочу создать контектор AppState, который использует собственный тип AppState. 'public struct OSXAppState: AppState {}'. Без AppStateType, как мне это сделать? Extension NSView: Subscriber {public func handleNewState (newState: OSXAppState) {}} '(newState: ** OSXAppState **) – joels

+0

Я обновил ответ, чтобы понять, как вы используете этот код. – ColGraff

+0

Спасибо! Итак, как мне реализовать структуру, которая соответствует AppStore? Использование, которое я использую только для NSView, но я бы разрешил все, что соответствует подписчику. Я обновил код своего использования, чтобы включить OSXAppStore. – joels

Смежные вопросы