Last active
July 13, 2018 23:43
-
-
Save albertbori/d3a1f134d58da300f064f5af030ea6ef to your computer and use it in GitHub Desktop.
NotificationCenter alternative using delegates (fully swift)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import PlaygroundSupport | |
//class that allows fully-swift weak reference storage for arrays/dictionaries | |
class Weak<T> { | |
private weak var _object: AnyObject? | |
var object: T? { return _object as? T } | |
init(object: T) { | |
_object = object as AnyObject | |
} | |
} | |
//The base class for handleing multiple delegates for a single purpose | |
class DelegateNotification<T> { | |
fileprivate var delegates: [Weak<T>] = [] | |
private var _serialQueue = DispatchQueue(label: "\(DelegateNotification.self)", qos: .background) | |
func listen(on delegate: T) { | |
_serialQueue.async { | |
self.delegates.append(Weak(object: delegate)) | |
} | |
cleanDelegates() | |
} | |
func callDelegates(withBlock block: @escaping (T)->()) { | |
_serialQueue.async { | |
for delegateRef in self.delegates { | |
if let delegate = delegateRef.object { | |
DispatchQueue.main.async { | |
block(delegate) | |
} | |
} | |
} | |
} | |
cleanDelegates() | |
} | |
private func cleanDelegates() { | |
_serialQueue.async { | |
self.delegates = self.delegates.filter({ $0.object != nil }) | |
} | |
} | |
} | |
//static class for convenience | |
class LocalNotifications { | |
static var replyCreated = ReplyCreatedNotification() | |
} | |
//sample protocol and associated DelegateNotification subclass | |
protocol ReplyCreatedDelegate: class { | |
func handleReplyCreated(reply: String) | |
} | |
class ReplyCreatedNotification: DelegateNotification<ReplyCreatedDelegate>, ReplyCreatedDelegate { | |
func handleReplyCreated(reply: String) { | |
super.callDelegates(withBlock: { $0.handleReplyCreated(reply: reply) }) | |
} | |
} | |
//usage | |
class Test: ReplyCreatedDelegate { | |
init() { | |
LocalNotifications.replyCreated.listen(on: self) | |
} | |
func handleReplyCreated(reply: String) { | |
print("handled new reply: \"\(reply)\"") | |
} | |
} | |
print("Testing...") | |
var test: Test? = Test() | |
LocalNotifications.replyCreated.handleReplyCreated(reply: "Hi!") //prints handled new reply: "Hi!" | |
test = nil | |
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) { //delay for deallocation | |
LocalNotifications.replyCreated.handleReplyCreated(reply: "Bye!") //does nothing. No listeners exist | |
print("\(LocalNotifications.replyCreated.delegates.count)") //prints 0. Deallocated listeners were removed | |
} | |
PlaygroundPage.current.needsIndefiniteExecution = true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment