Introduction
PromiseKit provides a promise-based abstraction for asynchronous operations on Apple platforms. It transforms deeply nested callback pyramids into linear, readable chains of then, map, done, and catch blocks. The library predates Swift's native async/await and remains useful for codebases that need Objective-C interop or gradual migration.
What PromiseKit Does
- Wraps callback-based APIs into chainable Promise objects
- Provides firstly/then/done/catch syntax for linear async flow
- Includes extensions for UIKit, Foundation, CoreLocation, and other Apple frameworks
- Supports guaranteed finalization blocks that always execute regardless of success or failure
- Offers when() for parallel promise execution and race() for first-to-resolve semantics
Architecture Overview
At its core, a Promise represents a value that will resolve in the future to either a result or an error. Internally each promise holds a sealed state (pending, fulfilled, or rejected). Handlers registered via then/done/catch are queued and dispatched on a configurable DispatchQueue when the promise resolves. The Guarantee type provides a non-failable variant for operations that cannot error.
Self-Hosting & Configuration
- Install via SPM: add the mxcl/PromiseKit package
- Or via CocoaPods:
pod 'PromiseKit', '~> 8.0' - Framework extensions (e.g., PMKFoundation, PMKCoreLocation) are separate packages
- Default dispatch queue for handlers is .main; configurable per chain
- Compatible with iOS 13+, macOS 10.15+, and Swift 5.5+
Key Features
- Eliminates callback nesting with a flat promise chain syntax
- Automatic error propagation through the chain until a catch block handles it
- Thread-safe state management for concurrent promise resolution
- Bridge between Objective-C completion-handler APIs and modern Swift code
- Interoperates with Swift async/await via promise.value
Comparison with Similar Tools
- Swift async/await — native language feature; PromiseKit bridges older callback APIs that lack async variants
- Combine — reactive streams framework by Apple; heavier for simple one-shot async operations
- RxSwift — full reactive programming; overkill when you only need promise semantics
- Hydra — lighter promise library; smaller community and fewer framework extensions
- Google Promises — Objective-C first; less idiomatic Swift API
FAQ
Q: Should I use PromiseKit or Swift async/await for new code? A: For new Swift-only code, prefer async/await. PromiseKit is valuable for wrapping legacy callback APIs and mixed Swift/ObjC codebases.
Q: Can PromiseKit promises be cancelled? A: PromiseKit does not natively support cancellation. For cancellable work, combine it with Task or Combine cancellation tokens.
Q: How does error handling work across a promise chain? A: Errors propagate automatically through the chain. The first catch block encountered handles the error; subsequent then/done blocks are skipped.
Q: Is PromiseKit thread-safe? A: Yes. Promise resolution and handler dispatch are thread-safe. You can resolve a promise from any thread.