Skip to content

Instantly share code, notes, and snippets.

@albertbori
Last active July 13, 2018 23:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save albertbori/d3a1f134d58da300f064f5af030ea6ef to your computer and use it in GitHub Desktop.
Save albertbori/d3a1f134d58da300f064f5af030ea6ef to your computer and use it in GitHub Desktop.
NotificationCenter alternative using delegates (fully swift)
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