PromiseKit is among the most successful promise frameworks for Swift, with over 900 forks at the time of writing. It employs a rather custom working for the functions that you use to build an asynchronous workflow, but it also includes a number of extensions that convert most Apple APIs to use promises. This is a big boon since, if the framework you choose does not include such conversion wrappers for you, you will need to create them on your own.
If you want to use PromiseKit, the first step is adding it as a dependency to your project. For the Swift Package Manager, this is what you should add to your Package.swift file:
let package = Package(
// ...
dependencies: [
.package(url: "https://github.com/mxcl/PromiseKit", majorVersion: 6),
],
// ...
)
If you use CocoaPods, just add the following to your Podfile:
pod "PromiseKit", "~> 6.0"
Then, refresh your dependencies by running the following command:
pod install
Similarly, for Carthage, add the following to your Cartfile:
github "mxcl/PromiseKit" ~> 6.0
Then run the following command:
carthage update
Once you have added the Promises framework dependency to your project, you can import the Promises module into your Swift source files as follows:
import PromiseKit
As an example, let's fetch some data from GitHub using their REST API. This is how our promise-based code could look. To keep things simple, we do not decode the resulting JSON, but simply print it out as a String.
func testGitHubAPI() {
if var urlComponents = URLComponents(string: "https://api.github.com/search/repositories") {
urlComponents.query = "q=sort=stars;order=desc;per_page=1"
let url = urlComponents.url!
URLSession.shared.dataTask(.promise, with: url)
.then { data -> Promise<(data: Data, response: URLResponse)> in
let string = String(data:data.data, encoding:String.Encoding.utf8)
print("Most starred repo: \(string!)")
urlComponents.query = "q=forks=stars;order=desc;per_page=1"
return URLSession.shared.dataTask(.promise, with: urlComponents.url!)
}
.then { data -> Promise<Data> in
let string = String(data:data.data, encoding:String.Encoding.utf8)
print("Most forked repo: \(string!)")
return Promise<Data> { seal in seal.fulfill(data.data)}
}
.catch { error in
print("This was unexpected: \(error)")
}
}
}
Of course, we could have executed the two searches in parallel: PromiseKit even offers a specific when(fulfilled:) function to run multiple async tasks at the same time, but we have done it sequentially for the sake of this example.