CocoaPods trunk is moving to be read-only. Read more on the blog, there are 18 months to go.
TestsTested | ✓ |
LangLanguage | SwiftSwift |
License | MIT |
ReleasedLast Release | Apr 2017 |
SwiftSwift Version | 3.0 |
SPMSupports SPM | ✓ |
Maintained by Johan Sørensen.
A Swift implementation of a Future, which can be used to model and transform asynchronous results while making it easy to bounce results between dispatch queues
Futures in Eventually can be used to wrap existing APIs, or to create new APIs using Futures
func operation(completion: (Int) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) {
completion(42)
}
}
Future<Int> { resolve in
operation { value
resolve.success(value)
}
}.then { result in
switch result {
case .success(let value):
print("value is", value) // "value is 42"
case .failure(let error):
print("something went wrong:", error)
}
}
When initializing a Future the closure receives a “resolver”, this resolver is simply a closure that you will call with a FutureResult, a Result enum type which can be either .success
or .failure
.
There’s also a couple of short-hand methods available
func calculateAge() -> Future<Int> {
// ...
}
calculateAge().success { (value: Int) in
print("Success value from calling calculateAge() is", value)
}.failure { error in
print(The Future returned by calculateAge() gave us an error:", error)
}
A non-closure based API for resolving futures is also available
let future = Future<Int>
future.success { value in
...
}
future.resolve(success: age)
With Eventually it is possible to map()
one Future type to another, allowing us to compose and transform things easily
calculateAge().map({ (value: Int) -> String in
return "Age is \(age)"
}).success { value in
print(value) // "Age is 42"
}
Like always, chaining is possible so multiple transforms can be done
Most of the methods operating on a Future accepts an EvaluationContext that describes what GCD queue the operation should be called on
Future<String>(on: .background) { resolve
// Performed on a background queue (eg `DispatchQueue.global(qos: .background)`)
resolve.success("hello"))
}.map(on: .queue(someCustomQueue)) { value in
// will be called on the supplied DispatchQueue (`someCustomQueue`)
return value + " world"
}.map(on: .main) { value in
// Mapping occurs on the main thread
let label = UILabel()
label.text = value
return text
}.success { label in
// default is the `.main` context
self.view.addSubview(label)
}
Eventually is available as a CocoaPod (pod 'Eventually'
) and the Swift Package Manager. Framework installation is also available by dragging the Eventually.xcodeproj into your project or via Carthage.
Eventually has no dependencies outside of Foundation and Dispatch (GCD)
See the LICENSE file