SwiftEvents is a lightweight library for creating and observing events. It’s type safe, thread safe and with memory safety. It has functionality of delegation, NotificationCenter, key-value observing (KVO) and bindings in one simple API.
Features:
Type Safety: the concrete type value is delivered to the subscriber without the need for downcasting
Thread Safety: you can addSubscriber, trigger, removeSubscriber from any thread without issues
Memory Safety: automatic preventing retain cycles and memory leaks (with no need to specify [weak self] in closures); as well as automatic removal of subscribers when they are deallocated
Comprehensive unit test coverage
Installation
CocoaPods
To install SwiftEvents using CocoaPods, add this line to your Podfile:
pod 'SwiftEvents', '~> 1.1.1'
Carthage
To install SwiftEvents using Carthage, add this line to your Cartfile:
github "denissimon/SwiftEvents"
Swift Package Manager
To install SwiftEvents using the Swift Package Manager, add it to your Package.swift file:
With SwiftEvents, such a one-to-one connection can be done in just two steps:
Create an Event for the publisher
Subscribe to the Event
Example:
import Foundation
import SwiftEvents
// The publisher
class MyModel {
let didDownloadEvent = Event<UIImage?>()
func downloadImage(for url: URL) {
download(url: url) { image in
self.didDownloadEvent.trigger(image)
}
}
}
import UIKit
// The subscriber
class MyViewController: UIViewController {
let model = MyModel()
override func viewDidLoad() {
super.viewDidLoad()
model.didDownloadEvent.addSubscriber(target: self) { (self, image) in
if let image = image {
self.performUpdate(image)
}
}
}
func updateImage() {
model.downloadImage(for: /* image url */)
}
}
You can use the Event with any complex type, including multiple values like (UIImage, Int)?. You can also create several events (didDownloadEvent, onHTTPErrorEvent, etc), and trigger only what is needed.
NotificationCenter functionality
If notifications must be one-to-many, or two objects that need to be connected are too far apart, SwiftEvents can be used in three steps:
Create an EventService
Create Events which will be held by EventService
Subscribe to the appropriate Event
Example:
import SwiftEvents
public class EventService {
public static let get = EventService()
private init() {}
// Events
public let onDataUpdate = Event<String?>()
}
class Controller1 {
init() {
EventService.get.onDataUpdate.addSubscriber(target: self) { (self, data) in
print("Controller1: '\(data)'")
}
}
}
class Controller2 {
init() {
EventService.get.onDataUpdate.addSubscriber(target: self) { (self, data) in
print("Controller2: '\(data)'")
}
}
}
class DataModel {
private(set) var data: String? {
didSet {
EventService.get.onDataUpdate.trigger(data)
}
}
func requestData() {
// requesting code goes here
data = "some data"
}
}
let sub1 = Controller1()
let sub2 = Controller2()
let pub = DataModel()
pub.requestData()
// => Controller1: 'some data'
// => Controller2: 'some data'
KVO and bindings functionality
Just two steps again:
Replace the Type of property to observe with the Observable<Type>
Subscribe to the didChanged Event
Example:
import Foundation
import SwiftEvents
class ViewModel {
var infoLabel: Observable<String>
init() {
infoLabel = Observable<String>("last saved value")
}
func set(newValue: String) {
infoLabel.value = newValue
}
}
import UIKit
class View: UIViewController {
var viewModel = ViewModel()
@IBOutlet weak var infoLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
infoLabel.text = viewModel.infoLabel.value
viewModel.infoLabel.didChanged.addSubscriber(target: self) { (self, value) in
self.infoLabel.text = value.new
}
}
}
In this MVVM example, every time the ViewModel changes the value of observable property infoLabel, the View is notified with new and old values and updates the infoLabel.text.
You can use the infix operator <<< to set a new value for an observable property:
infoLabel <<< newValue
Properties of any class or struct can be observable.
Advanced topics
Manual removal of a subscriber
A subscriber can be removed from the Event subscribers manually:
To get the number of times the Event has been triggered:
let triggersCount = someEvent.triggersCount
Reset of triggersCount
To reset the number of times the Event has been triggered:
someEvent.resetTriggersCount()
queue: DispatchQueue
By default, a subscriber’s handler is executed on the thread that triggers the Event. To change the default behaviour, you can set this parameter when adding a subscriber:
// This executes the subscriber's handler on the main queue
someEvent.addSubscriber(target: self, queue: .main) { (self, data) in
self.updateUI(data)
}
One-time notification
To remove a subscriber from the Event subscribers after a single notification:
// The handler of this subscriber will be executed only once
someEvent.addSubscriber(target: self) { (self, data) in
self.useData(data)
self.someEvent.removeSubscriber(target: self)
}
SwiftEvents
SwiftEvents is a lightweight library for creating and observing events. It’s type safe, thread safe and with memory safety. It has functionality of
delegation
,NotificationCenter
,key-value observing (KVO)
andbindings
in one simple API.Features:
Type Safety: the concrete type value is delivered to the subscriber without the need for downcasting
Thread Safety: you can
addSubscriber
,trigger
,removeSubscriber
from any thread without issuesMemory Safety: automatic preventing retain cycles and memory leaks (with no need to specify
[weak self]
in closures); as well as automatic removal of subscribers when they are deallocatedComprehensive unit test coverage
Installation
CocoaPods
To install SwiftEvents using CocoaPods, add this line to your
Podfile
:Carthage
To install SwiftEvents using Carthage, add this line to your
Cartfile
:Swift Package Manager
To install SwiftEvents using the Swift Package Manager, add it to your
Package.swift
file:Manual
Copy
SwiftEvents.swift
into your project.Usage
Delegation functionality
With SwiftEvents, such a
one-to-one
connection can be done in just two steps:Example:
You can use the Event with any complex type, including multiple values like
(UIImage, Int)?
. You can also create several events (didDownloadEvent, onHTTPErrorEvent, etc), and trigger only what is needed.NotificationCenter functionality
If notifications must be
one-to-many
, or two objects that need to be connected are too far apart, SwiftEvents can be used in three steps:Example:
KVO and bindings functionality
Just two steps again:
Type
of property to observe with theObservable<Type>
didChanged
EventExample:
In this MVVM example, every time the ViewModel changes the value of observable property
infoLabel
, the View is notified with new and old values and updates theinfoLabel.text
.You can use the infix operator <<< to set a new value for an observable property:
Properties of any class or struct can be observable.
Advanced topics
Manual removal of a subscriber
A subscriber can be removed from the Event subscribers manually:
Removal of all subscribers
To remove all Event subscribers:
subscribersCount
To get the number of subscribers to the Event:
triggersCount
To get the number of times the Event has been triggered:
Reset of triggersCount
To reset the number of times the Event has been triggered:
queue: DispatchQueue
By default, a subscriber’s handler is executed on the thread that triggers the Event. To change the default behaviour, you can set this parameter when adding a subscriber:
One-time notification
To remove a subscriber from the Event subscribers after a single notification:
License
Licensed under the MIT license