A type-safe broadcasting framework to replace NSNotificationCenter
Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
You can install Carthage with Homebrew using the following command:
$ brew update
$ brew install carthageTo integrate Beacon into your Xcode project using Carthage, specify it in your Cartfile:
github "zetasq/Beacon"
Run carthage update to build the framework and drag the built Beacon.framework into your Xcode project.
In Beacon, there are two kinds of roles: broadcaster and listener. Broadcasters send their signals to interested listeners.
It's easy to make your existing class a broadcaster by conforming to SignalBroadcasting. You only need to declare two subtypes: BroadcastIdentifier and BroadcastPayload.
This is like Notification.Name in the system Foundation framework. It needs to be RawRepresentable and has rawValue of type String. The easiest way is to use an enum whose rawValue is String.
You don't have to make the
rawValuestrings unique across your app or in other frameworks. Beacon will concatenate the bundle name, the broadcaster class name and therawValuestring to make an unique identifier.
// You have AccountManager to handle account related logic
extension AccountManager {
enum BroadcastIdentifier: String, BroadcastIdentifiable {
case userLogin
case userLogout
}
}This is like the userInfo dictionary in Notification in the system Foundation framework, but BroadcastPayload is a concrete data type. You can use any data structure(struct, class, enum...) or make a typealias to an existing subtype.
extension AccountManager {
struct BroadcastPayload {
let username: String
let time: Date
}
}Don't forget add the
SignalBroadcastingconformance:extension AccountManager: SignalBroadcasting {}
After you define the broadcasters, you can use them to broadcast signals.
let accountManager = AccountManager.shared
accountManager.broadcast(identifier: .userLogin, payload: .init(username: "Mr. Anderson", time: Date()))
accountManager.broadcast(identifier: .userLogout, payload: .init(username: "Mr. Smith", time: Date()))As a listener, you want to listen to certain kinds of broadcasting(and maybe from a certain broadcaster!).
class InterfaceController {
init() {
Beacon.default.addListener(self, broadcasterType: AccountManager.self, broadcastIdentifier: .userLogin) { [weak self] signal in
self?.handleUserLogin(info: signal.payload)
}
Beacon.default.addListener(self, broadcasterType: AccountManager.self, broadcastIdentifier: .userLogout) { [weak self] signal in
self?.handleUserLogout(info: signal.payload)
}
}
func handleUserLogin(info: AccountManager.BroadcastPayload) {
// do something when user login
}
func handleUserLogout(info: AccountManager.BroadcastPayload) {
// do something when user logout
}
}IMPORTANT: If you want to reference the listener(directly or indirectly), make sure you have added necessary
weakreferences in the signal callback closures. Otherwise the listeners will never be released!
Beacon is released under the MIT license. See LICENSE for details.