A thoughtfully designed reactive programming framework in Swift.
Pledge is a lightweight, thread-safe reactive programming framework for Swift that simplifies state management, event propagation and balances power with simplicity in your applications. While other frameworks force you to learn complex concepts and operators, Pledge focuses on solving the real problems developers face daily:
Overview
Pledge provides a clean, flexible way to implement the observer pattern in Swift applications. It enables you to create observable values that notify subscribers of changes, with powerful features like:
Thread-safe implementation
Priority-based notifications
Customizable delivery queues
Batch updates
Rate limiting (throttling and debouncing)
Functional operators (map, filter, etc.)
Global state management
Installation
Swift Package Manager
Add the following to your `Package.swift` file:
dependencies: [
.package(url: "https://github.com/gokulnair2001/Pledge.git", from: "1.0.0")
]
Core Components
PLObservable
`PLObservable` is the heart of Pledge, representing a thread-safe container for a value that can be observed for changes.
let messageObservable = PLObservable("Hello")
let subscription = messageObservable.subscribe { newMessage in
print("Message changed to: \(newMessage)")
}
messageObservable.setValue("Hello World")
PLGlobalStore
`PLGlobalStore` provides a centralized repository for observables, acting as a lightweight state management solution.
let store = PLGlobalStore.shared
let userNameObservable = store.string(for: "userName", defaultValue: "Guest")
userNameObservable.subscribe { name in
print("User name is now: \(name)")
}
PLGlobalStore.shared.string(for: "userName").setValue("John")
How Observables Work ?

The diagram above illustrates the flow of data in Pledge:
1. An observable holds a value and maintains a list of subscribers
2. When the value changes, all subscribers are notified in priority order
3. Subscribers can specify delivery queues for thread-safety
4. Optional rate limiting can control notification frequency
API Reference
PLObservable
Creating an Observable
let counter = PLObservable(0)
let isEnabled = PLObservable(true)
let userData = PLObservable(["name": "Guest", "role": "User"])
Subscribing to Changes
let subscription = observable.subscribe { newValue in
print("Value changed to: \(newValue)")
}
observable.unsubscribe(subscription)
observable.removeAllSubscribers()
Controlling Delivery
observable.deliver(on: myCustomQueue).subscribe { value in
}
observable.deliverOnMain().subscribe { value in
}
observable.withPriority(.high).subscribe { value in
}
Modifying Values
observable.setValue(newValue)
observable.setValue(newValue, notify: false)
observable.notifyObservers()
Batch Updates
observable.beginUpdates()
observable.setValue(1)
observable.setValue(2)
observable.setValue(3)
observable.endUpdates()
Rate Limiting
observable.throttle(for: 0.5).subscribe { value in
}
observable.debounce(for: 0.3).subscribe { value in
}
Operators
Transformation
let stringCounter = counter.map { "Count: \($0)" }
let userDetails = userIdObservable.flatMap { userId in
return fetchUserDetails(userId)
}
let optionalValue = PLObservable<String?>("test")
let unwrapped = optionalValue.compactMap()
Filtering
let evenNumbers = counter.filter { $0 % 2 == 0 }
let skipFirst = counter.skip(2)
let distinct = values.distinctUntilChanged()
Combining
let allEvents = userEvents.merge(systemEvents)
let credentials = username.zip(password)
PLGlobalStore
let counter = PLGlobalStore.shared.integer(for: "counter")
let userName = PLGlobalStore.shared.string(for: "userName")
let settings = PLGlobalStore.shared.dictionary(for: "settings")
let items = PLGlobalStore.shared.array(for: "items")
let isEnabled = PLGlobalStore.shared.boolean(for: "isEnabled")
PLGlobalStore.shared.removeObservable(for: "counter")
PLGlobalStore.shared.removeAllObservables()
Usage Examples
Form Validation
let username = PLObservable("")
let password = PLObservable("")
let isFormValid = PLObservable(false)
let isUsernameValid = username.map { $0.count >= 3 }
let isPasswordValid = password.map { $0.count >= 8 }
isUsernameValid.subscribe { usernameValid in
isPasswordValid.subscribe { passwordValid in
isFormValid.setValue(usernameValid && passwordValid)
}
}
isFormValid.subscribe { valid in
submitButton.isEnabled = valid
}
Network State Management
enum NetworkState {
case idle, loading, success(Data), error(Error)
}
let networkState = PLObservable<NetworkState>(.idle)
networkState.subscribe { state in
switch state {
case .idle:
case .loading:
case .success(let data):
case .error(let error):
}
}
func fetchData() {
networkState.setValue(.loading)
apiClient.fetchData { result in
switch result {
case .success(let data):
networkState.setValue(.success(data))
case .failure(let error):
networkState.setValue(.error(error))
}
}
}
Throttled Search
let searchQuery = PLObservable("")
searchQuery.throttle(for: 0.3).subscribe { query in
if !query.isEmpty {
performSearch(query)
}
}
Check the Github link to know more!!