In short I am struggling with an error "ObjectWithGeneric requires that MyProtocol be a class type". I created a small example that (hopefully) makes sense, to simulate the issue.
I created an array-like container that can hold weak references to generic types:
class Container<Type> where Type: AnyObject {
private class WeakWrapper {
weak var listener: Type?
init(listener: Type) { self.listener = listener }
}
private var wrappers: [WeakWrapper] = [WeakWrapper]()
func append(_ listener: Type) {
wrappers = wrappers.filter { $0.listener != nil && $0.listener !== listener } + [WeakWrapper(listener: listener)]
}
func remove(_ listener: Type) {
wrappers = wrappers.filter { $0.listener != nil && $0.listener !== listener }
}
func forEach(_ execution: ((_ listener: Type) -> Void)) {
wrappers.forEach { wrapper in
guard let listener = wrapper.listener else { return }
execution(listener)
}
}
}
All good so far. A small functionality to add and remove objects and a bit of a cleanup for objects that are deallocated.
Then I created a manager with a singleton that should hold such an array as "delegates". So instead of one weak delegate we would have an array of them. So a simple protocol:
protocol ExampleProtocol: class {
func showMessage(_ message: String)
}
And a simple manager
class ExampleManager {
static let shared: ExampleManager = ExampleManager()
var delegates: Container<ExampleProtocol> = Container<ExampleProtocol>()
private func sendMessageToAll() {
delegates.forEach { $0.showMessage("Ping") }
}
}
Some examples of usage:
class ExampleClass: ExampleProtocol {
init() {
ExampleManager.shared.delegates.append(self)
}
func showMessage(_ message: String) { print(message) }
}
class ExampleViewController: UIViewController, ExampleProtocol {
override func viewDidLoad() {
super.viewDidLoad()
ExampleManager.shared.delegates.append(self)
}
func showMessage(_ message: String) { print("A controller says: \(message)") }
}
The compile problem is on the line var delegates: Container<ExampleProtocol> = Container<ExampleProtocol>()
. It says that "'Container' requires that 'ExampleProtocol' be a class type.".
This kind of does and doesn't make sense to me. The protocol is defined as class
but I guess the protocol itself is not a concrete class. So perhaps there should be way to define it as AnyObject
that corresponds to ExampleProtocol
. Like Container<AnyObject : ExampleProtocol>
. But so far I have no luck achieving this.
Any clue appreciated. Thank You!