Swift delegate for a generic class - swift

I have a class that needs to call out to a delegate when one of its properties changes. Here are the simplified class and protocol for the delegate:
protocol MyClassDelegate: class {
func valueChanged(myClass: MyClass)
}
class MyClass {
weak var delegate: MyClassDelegate?
var currentValue: Int {
didSet {
if let actualDelegate = delegate {
actualDelegate.valueChanged(self)
}
}
}
init(initialValue: Int) {
currentValue = initialValue
}
}
This all works just fine. But, I want to make this class generic. So, I tried this:
protocol MyClassDelegate: class {
func valueChanged(genericClass: MyClass)
}
class MyClass<T> {
weak var delegate: MyClassDelegate?
var currentValue: T {
didSet {
if let actualDelegate = delegate {
actualDelegate.valueChanged(self)
}
}
}
init(initialValue: T) {
currentValue = initialValue
}
}
This throws two compiler errors. First, the line declaring valueChanged in the protocol gives: Reference to generic type 'MyClass' requires arguments in <...>. Second, the call to valueChanged in the didSet watcher throws: 'MyClassDelegate' does not have a member named 'valueChanged'.
I thought using a typealias would solve the problem:
protocol MyClassDelegate: class {
typealias MyClassValueType
func valueChanged(genericClass: MyClass<MyClassValueType>)
}
class MyClass<T> {
weak var delegate: MyClassDelegate?
var currentValue: T {
didSet {
if let actualDelegate = delegate {
actualDelegate.valueChanged(self)
}
}
}
init(initialValue: T) {
currentValue = initialValue
}
}
I seem to be on the right path, but I still have two compiler errors. The second error from above remains, as well as a new one on the line declaring the delegate property of MyClass: Protocol 'MyClassDelegate' can only be used as a generic constraint because it has Self or associated type requirements.
Is there any way to accomplish this?

It is hard to know what the best solution is to your problem without having more information, but one possible solution is to change your protocol declaration to this:
protocol MyClassDelegate: class {
func valueChanged<T>(genericClass: MyClass<T>)
}
That removes the need for a typealias in the protocol and should resolve the error messages that you've been getting.
Part of the reason why I'm not sure if this is the best solution for you is because I don't know how or where the valueChanged function is called, and so I don't know if it is practical to add a generic parameter to that function. If this solution doesn't work, post a comment.

You can use templates methods with type erasure...
protocol HeavyDelegate : class {
func heavy<P, R>(heavy: Heavy<P, R>, shouldReturn: P) -> R
}
class Heavy<P, R> {
typealias Param = P
typealias Return = R
weak var delegate : HeavyDelegate?
func inject(p : P) -> R? {
if delegate != nil {
return delegate?.heavy(self, shouldReturn: p)
}
return nil
}
func callMe(r : Return) {
}
}
class Delegate : HeavyDelegate {
typealias H = Heavy<(Int, String), String>
func heavy<P, R>(heavy: Heavy<P, R>, shouldReturn: P) -> R {
let h = heavy as! H // Compile gives warning but still works!
h.callMe("Hello")
print("Invoked")
return "Hello" as! R
}
}
let heavy = Heavy<(Int, String), String>()
let delegate = Delegate()
heavy.delegate = delegate
heavy.inject((5, "alive"))

Protocols can have type requirements but cannot be generic; and protocols with type requirements can be used as generic constraints, but they cannot be used to type values. Because of this, you won't be able to reference your protocol type from your generic class if you go this path.
If your delegation protocol is very simple (like one or two methods), you can accept closures instead of a protocol object:
class MyClass<T> {
var valueChanged: (MyClass<T>) -> Void
}
class Delegate {
func valueChanged(obj: MyClass<Int>) {
print("object changed")
}
}
let d = Delegate()
let x = MyClass<Int>()
x.valueChanged = d.valueChanged
You can extend the concept to a struct holding a bunch of closures:
class MyClass<T> {
var delegate: PseudoProtocol<T>
}
struct PseudoProtocol<T> {
var valueWillChange: (MyClass<T>) -> Bool
var valueDidChange: (MyClass<T>) -> Void
}
Be extra careful with memory management, though, because blocks have a strong reference to the object that they refer to. In contrast, delegates are typically weak references to avoid cycles.

Related

Weak reference implementing a (generic) protocol

I want to create an array of weak references implementing a protocol for observable functionality.
If possible this protocol should have an associated type, so I would not need to create identical ones for each type.
However in Swift 4 this does not seem to work, what I want is basically this:
protocol DelegateBase: AnyObject {
associatedtype Item
func onDataUpdated(data: [Item])
}
protocol Delegate : DelegateBase where Item == Int {
// Will have func onDataUpdated(data: [Int])
}
// T should be a class implementing Delegate, but cannot find a way to
// define T in a way that the Swift compiler accepts it
class WeakListener<T> {
weak var listener : T?
init(listener: T) {
self.listener = listener
}
}
class Implementation {
val listeners = [WeakListener<Delegate>]()
}
If I define everything as non-generic I can make it work, but I would like the convenience of not having to copy paste a concrete version of DelegateBase for each type I want to support.
// This works but is clunky
protocol DelegateA {
func onDataUpdated(data: [Int])
}
// DelegateB with type Double, DelegateC with type X
class WeakListenerA {
weak var listener : DelegateA?
init(listener: DelegateA) {
self.listener = listener
}
}
// WeakListenerB with type Double, WeakListenerC with type X
class ImplementationA {
val listeners = [WeakListenerA]()
}
// ImplementationB with type Double, ImplementationC with type X
EDIT: Intended usage
Basically I want to implement remote-backed repository where UIViewControllers can listen in on events happening inside the repository even though they aren't actively requesting data.
I want the listener to be generic, so I don't need to clone everything for each type. I want weak references since then no manual work is needed for managing them apart from adding listeners.
protocol DelegateBase: AnyObject {
associatedtype Item
func onDataModified(data: [Item])
func onDataRefreshed(data: [Item])
}
protocol IntDelegate : DelegateBase where Item == Int {
// Will have
//func onDataModified(data: [Int])
//func onDataRefreshed(data: [Int])
}
// Listener should implement the delegate T, that extends DelegateBase
// with a type
class WeakListener<T : DelegateBase> {
weak var listener : T?
init(listener: T) {
self.listener = listener
}
}
class IntRepository {
var listeners = [WeakListener<IntDelegate>]()
var data = [Int]()
func addListener(_ listener: IntDelegate /* UIViewController implementing IntDelegate*/) {
listeners.add(listener)
}
func add() {
// data is updated, notify weak listeners
data.append(1)
for listener in listeners {
listener.listener?.onDataModified(data: data)
}
}
func refresh() {
// data refreshed from a remote source
for listener in listeners {
listener.listener?.onDataRefreshed(data: data)
}
}
fileprivate func cleanupListeners() {
self.listeners = self.listeners.filter({$0.listener != nil})
}
// Singleton for example
fileprivate static var _instance: IntImplementation!
public class func shared() -> IntImplementation {
if _instance == nil {
_instance = IntImplementation()
}
return _instance!
}
}
class IntViewController: UIViewController, IntDelegate {
override func viewDidLoad() {
IntImplementation.shared().addListener(self)
}
func onDataModified(data: [Int]) {
// update UI
}
func onDataRefreshed(data: [Int]) {
// update UI
}
}
Because the DelegateBase (and by extension, the Delegate) protocol has an associated type (unlike DelegateA), you cannot use it as a type; you can only use some concrete type that conforms to it.
For what you're trying to do, you don't actually need the Delegate protocol. You seem to want a WeakListener generic with respect to Item type, which you can declare like so:
class WeakListener<T: DelegateBase> {
weak var listener : T?
init(listener: T) {
self.listener = listener
}
}
In other words, the above works with some concrete T type that conforms to DelegateBase.
Let's say you had such a concrete type for Int:
class ConcreteIntDelegateA: DelegateBase {
func onDataUpdated(data: [Int]) {
// ...
}
}
Then you could create a WeakListener for ConcreteIntDelegateA because it conforms to DelegateBase and further specifies that an Item is Int
let listener: WeakListener<ConcreteIntDelegateA>
So, it works for a concrete type, but you cannot do this for a protocol DelegateBase, because DelegateBase doesn't conform to DelegateBase (protocols don't conform to protocols, including themselves):
let listener: WeakListener<DelegateBase> // ERROR
This gives you the ability to create array of listeneres for a specific concrete type, e.g. [WeakListener<ConcreteIntDelegateA>] or [WeakListener<ConcreteIntDelegateB>], but not mixed, because these types are unrelated even though both ConcreteDelegateX conform to DelegateBase.
To get around it is to create a type-erased type, e.g. class AnyDelegate<Item>: DelegateBase, which takes a concrete type in its init:
class AnyDelegate<Item>: DelegateBase {
private let onDataUpdated: ([Item]) -> Void
init<C: DelegateBase>(_ c: C) where C.Item == Item {
self.sonDataUpdated = c.onDataUpdated(data:)
}
func onDataUpdated(data: [Item]) {
onDataUpdated(data)
}
}
let anyIntA = AnyDelegate(ConcreteIntDelegateA())
let anyIntB = AnyDelegate(ConcreteIntDelegateB())
let anyIntListeners: [WeakListener<AnyDelegate<Int>>] = [anyIntA, anyIntB]
What I ended up doing was just throwing away the DelegateBase. To provide some type conformance I created a generic base repository and enforce the delegate type during runtime when adding listeners
import UIKit
protocol IntDelegate : AnyObject {
func onDataModified(data: [Int])
func onDataRefreshed(data: [Int])
}
class WeakListener {
weak var listener : AnyObject?
init(listener: AnyObject) {
self.listener = listener
}
}
class RepositoryBase<T> {
private var _listeners = [WeakListener]()
var listeners: [T] {
get {
// Remove dead listeners
self._listeners = self._listeners.filter({($0.listener as? T) != nil})
return self._listeners.map({ $0.listener as! T })
}
}
func addListener(_ listener: AnyObject) {
assert(listener is T)
_listeners.append(WeakListener(listener: listener))
}
}
class IntRepository : RepositoryBase<IntDelegate> {
var data = [Int]()
func add() {
// data is updated, notify weak listeners
data.append(1)
for listener in self.listeners {
listener.onDataModified(data: data)
}
}
func refresh() {
// data refreshed from a remote source
for listener in self.listeners {
listener.onDataRefreshed(data: data)
}
}
// Singleton for example
fileprivate static var _instance: IntRepository!
public class func shared() -> IntRepository {
if _instance == nil {
_instance = IntRepository()
}
return _instance!
}
}
class IntViewController: IntDelegate {
func viewDidLoad() {
IntRepository.shared().addListener(self)
IntRepository.shared().add()
}
func onDataModified(data: [Int]) {
print("modified")
}
func onDataRefreshed(data: [Int]) {
print("refreshed")
}
}
IntViewController().viewDidLoad() // Prints "modified"

type A requires that type B be a class type swift 4

the following code gives me a compile error
'WeakReference' requires that 'ServiceDelegate' be a class type
protocol ServiceDelegate: AnyObject {
func doIt()
}
class SomeClass() {
// compile error occurs in this line
private var observers = [WeakReference<ServiceDelegate>]()
}
WeakReference code:
final class WeakReference<T: AnyObject> {
private(set) weak var value: T?
init(value: T?) {
self.value = value
}
}
How can I fix this error? Delegate should be declared correctly as per this site.
What I have tried so far:
Changing the delegate protocol conformance from AnyObject to
class does not solve the problem.
Try the above code in a clean playground.
You can't have a WeakReference<ServiceDelegate>. ServiceDelegate itself is not an AnyObject, it just requires that anything that conforms to it be an AnyObject.
You would need to make SomeClass generic and use the generic type as the type for the WeakReference:
class SomeClass<T: ServiceDelegate> {
private var observers = [WeakReference<T>]()
}
If the generic on SomeClass is too constricting and you want to be able to have instances of multiple unrelated classes as observers then I would do it by abandoning the generic parameter on WeakReference:
final class WeakServiceDelegate {
private(set) weak var value: ServiceDelegate?
init(value: ServiceDelegate?) {
self.value = value
}
}
class SomeClass {
private var observers = [WeakServiceDelegate]()
}
Alternatively you could make WeakReference conditionally conform to ServiceDelegate:
extension WeakReference: ServiceDelegate where T: ServiceDelegate {
func doIt() {
value?.doIt()
}
}
And then use an array of ServiceDelegate in SomeClass:
class SomeClass {
private var observers = [ServiceDelegate]()
func addObserver<T: ServiceDelegate>(_ observer: T) {
observers.append(WeakReference(value: observer))
}
}
As you see, ServiceDelegate is a protocol, not a class type.
Even if all types which can conform to ServiceDelegate are class types, ServiceDelegate itself is not a class type. It is the fact of the pure Swift protocols currently.
Try #obc, Objective-C protocols are a bit different:
#objc protocol ServiceDelegate {
func doIt()
}
You may want to exclude Objective-C something and to make some pure Swift classes conform to ServiceDelegate, but I cannot find other ways around.
The problem is that WeakReference<ServiceDelegate> is wrong at line
private var observers = [WeakReference<ServiceDelegate>]()
You have to use a concrete class instead of protocol inside <>
You have two possible solutions:
Create a concrete class and use it:
class ServiceClass: ServiceDelegate {
//...
}
private var observers = [WeakReference<ServiceClass>]()
Or use a protocol. I mean this:
final class WeakReference<T: AnyObject> {
private(set) weak var value: T?
init(value: T?) {
self.value = value
}
}
protocol SomeContainer: AnyObject { }
extension WeakReference: SomeContainer { }
and use this way:
private var observers = [SomeContainer]()
Note
Using this way:
class SomeClass<T: ServiceDelegate> {
private var observers = [WeakReference<T>]()
}
You just move the problem to another part of the code.
I had similar problem and ended up keeping generic WeakReference, but removing type constraint:
struct WeakReference<T> {
private weak var storage: AnyObject?
var value: T? {
get { return storage.map { $0 as! T } }
set {
storage = newValue.map { $0 as AnyObject }
}
}
init(value: T?) {
self.value = value
}
}
This works for classes, Objective-C protocols and Swift protocols:
protocol P: class {}
#objc protocol Q {}
class Z: P, Q {}
var z = Z()
var rz = WeakReference<Z>(value: z)
var rp = WeakReference<P>(value: z)
var rq = WeakReference<Q>(value: z)
assert(rz.value === z)
assert(rp.value === z)
assert(rq.value === z)
z = Z()
assert(rz.value === nil)
assert(rp.value === nil)
assert(rq.value === nil)
Unfortunately it compiles for other things too:
protocol R {}
struct S: R {}
var rr = WeakReference<R>(value: S())
print("rr =", rr.value as Any) // nil
var rs = WeakReference<S>(value: S())
print("rs =", rs.value as Any) // nil
In Swift anything can be casted to AnyObject, but for value types that means boxing - new instance is allocated and immediately lost, so it always produces nil.
This can be used to implement an assertion that casting to AnyObject preserves identity:
struct WeakReference<T> {
private weak var storage: AnyObject?
var value: T? {
get { return storage.map { $0 as! T } }
set {
storage = newValue.map {
let asObject = $0 as AnyObject
assert(asObject === $0 as AnyObject)
return asObject
}
}
}
init(value: T?) {
self.value = value
}
}
Alternative approach would be to use https://github.com/wickwirew/Runtime to validate kind of T.self.
create plain protocol
public protocol AnyWeakValue {
var anyValue: Any? { get }
}
inherit associatedtype protocol from AnyWeakValue
public protocol WeakValue: AnyWeakValue {
associatedtype ValueType
var value: ValueType? { get }
}
extension WeakValue {
public var anyValue: Any? { return value }
}
create class Weak inherit WeakValue
open class Weak<Value: AnyObject>: WeakValue {
public init(value: Value?) { self.value = value }
open private(set) weak var value: Value?
}
using example
private var _delegates: [AnyWeakValue] = []
public var delegates: [SomeProtocol] {
return _delegates.compactMap({$0.anyValue as? SomeProtocol})
}
public func register<Delegate>(_ delegate: Delegate) where Delegate: SomeProtocol {
let weak: Weak<Delegate> = Weak.init(value: delegate)
_delegates.append(weak)
}

Use generic struct with protocol

It seems that Swift generics work fine, as long as I don't try to combine them in any practical way. I'm using Swift 4.1, and I would like to create a generic array containing only weak references. I can define this as WeakList<T>. So far so well. But: I would like to use a protocol for T. Swift says nope..
import Foundation
protocol Observer: class {
func stateChanged(sender: SomeClass, newState: Int)
}
struct WeakList<T> where T: AnyObject {
struct Ptr {
weak var p: T?
}
private var storage: [Ptr] = []
var aliveObjects: [T] {
var result: [T] = []
for ptr in storage {
if let p = ptr.p {
result.append(p)
}
}
return result
}
mutating func add(_ obj: T) {
storage.append(Ptr(p: obj))
}
// Let's ignore for a moment that this implementation leaks memory badly.
}
class SomeClass {
var someVar: WeakList<Observer> = WeakList<Observer>()
// Error: WeakList requires that 'Observer' be a class type
var thisIsOk: WeakList<NSObject> = WeakList<NSObject>()
}
(this is not my original code but a minimal verifyable example that contains enough details so that no one can say "just remove the AnyObject constraint from the structure")
I guess what I'm trying to do is just not possible. Or is it? It's just frustrating how 4 out of 5 times when I try to do something with Swift generics, I later learn that what I am trying to do is just not possible. (I can implement the same thing in Objective-C easily, by the way.)
I tried changing the class constraint to an AnyObject constraint => doesn't work either.
I tried to change the AnyObject constraint to a class constraint => doesn't even compile.
And changing it to protocol Observer where Self: NSObject doesn't change anything. NSObject is a class type, Observer is an NSObject. It should follow that Observer is a class type. The "is a" relationship doesn't seem to be transitive here.
With current implementation you cannot inherit the protocol from AnyObject. What you can do is to create a Type Eraser for your protocol and use that instead. Now your type eraser can be inherited from AnyObject.
Something like this:
protocol Observer {
func stateChanged(sender: SomeClass, newState: Int)
}
class AnyObserver: NSObject, Observer {
private let observer: Observer
init(observer: Observer) {
self.observer = observer
}
func stateChanged(sender: SomeClass, newState: Int) {
observer.stateChanged(sender: sender, newState: newState)
}
}
struct WeakList<T> where T: AnyObject {
struct Ptr {
weak var p: T?
}
private var storage: [Ptr] = []
var aliveObjects: [T] {
var result: [T] = []
for ptr in storage {
if let p = ptr.p {
result.append(p)
}
}
return result
}
mutating func add(_ obj: T) {
storage.append(Ptr(p: obj))
}
// Let's ignore for a moment that this implementation leaks memory badly.
}
class SomeClass {
var someVar: WeakList<AnyObserver> = WeakList<AnyObserver>()
var thisIsOk: WeakList<NSObject> = WeakList<NSObject>()
}

Generic class with generic delegate. How can I distinguish which object's delegate is executing the callback?

MyClass is a generic class which has a generic delegate.
AClass contains two iVar instances of MyClass and also implements MyClassDelegate.
Where AClass implements MyClassDelegate, how can I distinguish which object is calling into the interface? With non-generic classes, == is acceptable.
Please see the comments and error messages at the bottom of this code snippet.
protocol MyClassDelegate: class {
func myClass<T>(_ myClass: MyClass<T>, valueDidChange value: T)
}
class MyClass<T: Comparable> {
private var _value: T
var value: T {
set {
delegate?.myClass(self, valueDidChange: newValue)
}
get {
return _value
}
}
var delegate: MyClassDelegate?
init(value: T) {
_value = value
}
}
class AClass {
private var thing1 = MyClass(value: Int(10))
private var thing2 = MyClass(value: Int(100))
private var thing3 = MyClass(value: TimeInterval(10))
private var thing4 = MyClass(value: TimeInterval(100))
init() {
thing1.delegate = self
thing2.delegate = self
thing3.delegate = self
thing4.delegate = self
}
}
extension AClass: MyClassDelegate {
func myClass<T>(_ myClass: MyClass<T>, valueDidChange value: T) {
// This fails to complile
// Binary operator '==' cannot be applied to operands of type 'MyClass<T>' and 'MyClass<Int>'
if myClass == thing1 {
}
// Binary operator '==' cannot be applied to operands of type 'MyClass<T>' and 'MyClass<TimeInterval>' (aka 'MyClass<Double>')
else if myClass == thing3 {
}
}
}
Restrict the T type in your protocol method signature func myClass<T>(...) to be Comparable. Since you restricted it only in one particular extension of that protocol, the method in AClass can take any kind of T, not just Comparable ones.
I tried and tried but couldn't configure the generic delegate in a manner where I could compare callers.
I read the answer from NRitH, but couldn't get the compiler to accept the syntax. Perhaps there is a way to do this, but I went a different route with success.
I gave up on the protocol/delegate technique and ended up using a callback closure. Instead of defining a delegate in MyClass and implementing that delegate in AClass, I defined a callback closure in MyClass in implemented that in AClass like so:
class MyClass<T: Comparable>: Equatable {
var valueChanged: ((_ clazz: MyClass) -> Void)?
private var _value: T
var value: T {
set {
_value = newValue
valueChanged?(self)
}
get {
return _value
}
}
init(value: T) {
_value = value
}
static public func ==(lhs: MyClass<T>, rhs: MyClass<T>) -> Bool {
return lhs.value == rhs.value
}
}
class AClass {
fileprivate var thing1: MyClass<Int> = MyClass(value: 10)
fileprivate var thing2: MyClass<Int> = MyClass(value: 100)
fileprivate var thing3: MyClass<TimeInterval> = MyClass(value: 10)
fileprivate var thing4: MyClass<TimeInterval> = MyClass(value: 100)
init() {
thing1.valueChanged = { (thing) in
// You can compare here, but you already know which object is callling back
if thing == self.thing1 {
}
}
thing2.valueChanged = { (thing) in
print("Thing2 changed: \(thing.value)")
}
}
}

Writing a common subject-observer implementation in Swift

Let's say I have a class that implements a beautiful subject-observer pattern thus. (This is Swift 3; Swift 2 would be no different in essence.)
protocol Delegate : class
{
func method()
}
class Subject
{
private typealias WeakDelegate = WeakReference< Delegate >
private var nextAvailableDelegateId = 0
private var delegates = [ Int : WeakDelegate ]()
#discardableResult
public func addDelegate( _ delegate: Delegate ) -> Int
{
let id = nextAvailableDelegateId
nextAvailableDelegateId += 1
delegates[ id ] = WeakDelegate( value: delegate )
return id
}
public func removeDelegate( _ idForDelegate: Int )
{
delegates.removeValue( forKey: idForDelegate )
}
fileprivate func eachDelegate( fn: (Delegate) -> Void )
{
for (key, weakDelegate) in delegates
{
// Has this weak delegate reference become nil?
//
guard let delegate = weakDelegate.value else
{
// Yes. Remove it.
delegates.removeValue( forKey: key )
continue
}
fn( delegate )
}
}
private func exampleNotifier()
{
eachDelegate{ $0.method() }
}
}
(I'm taking the idiomatic Swift term "delegate" as roughly equivalent to the design pattern concept "observer".)
The WeakReference type above isn't strictly speaking part of this question, but in case you're curious:
public class WeakReference< T >
{
public var value: T?
{
return abstractValue as? T
}
public init( value: T )
{
abstractValue = value as AnyObject
}
private weak var abstractValue: AnyObject?
}
Now I want to create another class analogous to Subject with another delegate protocol analogous to Delegate. How do I use the implementation I've already written for Subject in the new class?
One answer is to copy and paste the code. Not a good answer.
In C++ we could create a true mixin, a class that contains all the code and data necessary to implement the Subject, templated on a generic Delegate type, and inherit from it wherever we want to make some other class act as a Subject. Quite trivial.
Protocols, protocol extensions, and generics seem to have some of the machinery necessary for this kind of code reuse, but I can't work out how to accomplish it.
Help?
You can use protocol inheritance and generics to derive from some basic protocol.
Each new delegate will inherit from a parent class:
protocol Delegate: class {
func method()
}
protocol DelegateA: Delegate { }
protocol DelegateB: Delegate { }
Your parent subject class can be implemented using a generic conforming to your parent protocol.
class Subject<T: Delegate> {
private typealias WeakDelegate = WeakReference<T>
private var nextAvailableDelegateId = 0
private var delegates = [Int: WeakDelegate]()
#discardableResult
public func addDelegate(_ delegate: T) -> Int {
let id = nextAvailableDelegateId
nextAvailableDelegateId += 1
delegates[id] = WeakDelegate( value: delegate )
return id
}
public func removeDelegate(_ idForDelegate: Int) {
delegates.removeValue(forKey: idForDelegate)
}
fileprivate func eachDelegate( fn: (T) -> Void ) {
for (key, weakDelegate) in delegates {
// Has this weak delegate reference become nil?
guard let delegate = weakDelegate.value else {
// Yes. Remove it.
delegates.removeValue( forKey: key )
continue
}
fn( delegate )
}
}
private func exampleNotifier() {
eachDelegate{ $0.method() }
}
}
Each new subject can be instantiated as a generic conforming to your child delegates.
class SubjectA<T: DelegateA>: Subject<T> { }
class SubjectB<T: DelegateB>: Subject<T> { }