0

I am trying to create a protocol (AppStore) which requires the conformer to implement an array of items (subscriptions) that conform to a protocol (Subscriber) that has an associated type.

goal You can think of AppStore like an NSNotificationCenter. I want to add subscribers (like addObserver...). When something happens call handleNewState on the subscribers (like handleNotification:) and pass in an AppState conformer that actually has some variables set on it. The stock AppState doesn't have any properties available.

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

How am I supposed to define var subscriptions:[Subscription<>]? Or should I be doing this a different way

I would use it like this

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
  • 1
    Can you describe your goal in more detail? What problem are you trying to solve with this code? This may not be the most direct way toward that goal. Commented Apr 27, 2016 at 14:45

1 Answer 1

1

I assume that you were adhering to AnyObject in order to be able to use weak. This can be done more simply by making the protocol class-only. I changed the protocol composition

protocol<Subscriber, AnyObject>

to

protocol Subscriber: class

I also added

associatedtype GenericSubscriber: SubscriberType

to allow the generic

Subscription<T: SubscriberType>

to be used in the array.

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){
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

The associatedtype AppStateType is the key piece here. I want to create an AppState conformer that uses it's own AppState type. public struct OSXAppState:AppState { }. Without AppStateType how do I do this extension NSView : Subscriber { public func handleNewState(newState: OSXAppState ){ } } (newState: OSXAppState )
I updated the answer to reflect how you are using the code.
Thank you! So, how would I implement a struct that conforms to AppStore? The use I have only allows NSView but I would to allow anything that conforms to Subscriber. I updated my use case code to include OSXAppStore.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.