I have been the last days fighting with some issues regarding generics on Swift, and I don't find a way to figure out how to achieve this:
- I have a class
class Store<S: State>
whereState
is a simple protocol which extends Equatableprotocol State: Equatable
. - I have a class
Logger
where I want to store an array ofStores
to keep track of each change on them and compare theirState
with their old values, being able to check what changes in each iteration.
For this, I need to store an array of Any Kind of Store in my logger class. The problem comes when I try to use a val storeArray = [Store<Any>]
, it doesn't work because Any is not an Equatable
type, and I will need them to extend Equatable
or NSObject
to be able to compare the states between them.
Is possible to achieve this in Swift? Or find out another way to compare 2 items without make a generic extend a Equatable
protocol?
In case you wanna check the implementation :
State :
protocol State: Equatable {
}
Store :
class Store<S: State> {
private var _initialState: S
private var _state: S
private var processor = PublishSubject<S>()
init(initialState: S) {
_initialState = initialState
_state = initialState
}
var state: S {
get {
return _state
}
set(value) {
if (value != state) {
_state = value
processor.onNext(value)
}
}
}
func initialState() -> S {
return _initialState
}
/// Initialize the store. Called after all stores instances are ready.
func initialize() {
//TODO Check if its possible to force an override over a method
preconditionFailure("This method must be overridden")
}
}
After the suggestion of Vadian I have tried to move it to a protocol with an associate type:
protocol Store: class {
associatedtype State : StateDelegate
var processor : PublishSubject<State> { get }
var _state : State { get set }
var state: State { get set }
func initialState() -> State
func flowable() -> Observable<State>
func initialize() -> Void
}
extension Store {
var state: State {
get {
return _state
}
set(value) {
if (value != state) {
_state = value
processor.onNext(value)
}
}
}
func flowable() -> Observable<State> {
return processor.startWith(state)
}
func initialState() -> State {
return State.init()
}
}
But I retrieve the next error when I try to create an [Store]
array:
Protocol 'Store' can only be used as a generic constraint because it has Self or associated type requirements