thomvis / brightfutures Goto Github PK
View Code? Open in Web Editor NEWWrite great asynchronous code in Swift using futures and promises
License: MIT License
Write great asynchronous code in Swift using futures and promises
License: MIT License
From the Scala docs:
"Returns whether the future has already been completed with a value or an exception."
This would be really helpful to have.
Probably best explained with a code example. I have a UIViewController which fetches data wrapped in BrightFutures, and on completion fills in that data in its views - simple enough:
class SomeViewController: UIViewController {
override func viewDidAppear() {
super.viewDidAppear()
// loadUser returns a Future
User.loadUser().onSuccess(callback: displayUser)
}
func displayUser(user: User) {
println("displaying user \(user)")
}
}
What happens if SomeViewController was deallocated before the loadUser future resolves? Does BrightFutures retain the callback method and the relevant object associated with it, or do I need to always wrap it in a 'weak self' wrapper like so:
User.loadUser().onSuccess { [weak self] user in
self?.displayUser(user)
}
I much prefer the first form - and preferably an even simpler one (currently the callback argument name is required). It's already a huge improvement over the existing success/failure block or delegate method approaches used, IMO.
(note: Swift 1.2, BrightFutures 2.x)
Hi @Thomvis,
In my current project, I need to use the dispatch_after() GCD function. I do like your Queue wrapper very much and I think it would be a great fit. Let me know if something like this would fit the philosophy behind this project. I've added a pull request for your review.
The completion callbacks and Result use failure
, while Promise uses the word error
. Is there any reason for this? It seems to me it would be more clear that one leads to another if they were both called either error
or failure
.
I could be wrong, but it looks like you have newer versions that are not in CocoaPods.
# pod search BrightFutures
-> BrightFutures (1.0.0-beta.3)
A simple Futures & Promises library for iOS and OS X written in Swift
pod 'BrightFutures', '~> 1.0.0-beta.3'
- Homepage: https://github.com/Thomvis/BrightFutures
- Source: https://github.com/Thomvis/BrightFutures.git
- Versions: 1.0.0-beta.3, 1.0.0-beta.2 [master repo]
I'll throw this one out there, no clue what's going on.
let foo: Future<String, ErrorType>
error: protocol type ErrorType
does not conform to protocol ErrorType
because ErrorType
is not declared @objc
// Custom protocols don't work either
protocol MyError: ErrorType {}
// and trying to make it @objc backfires
@objc public protocol MyObjCError: ErrorType {}
error: @objc protocol MyObjCError
cannot refine non-@objc protocol ErrorType
Any wizard has a magic spell to fix this one?
// this is ugly
enum FutureError : ErrorType {
case Error(ErrorType)
}
// and this is not kosher
class FutureError : ErrorType { }
Swift 2.0
XCode Version 7.0 beta 5 (7A176x)
Applying the map function on a future seems to never finish. The map block never gets executed. I tried debugging the map myself, even looking at the BrightFutures code by setting breakpoints there, but that has only caused xcode to seg fault (a lovely feature I keep seeing with swift). So I am stuck.
Here is the source of me using the map, the 'dummyAbbrDictF' function is the culprit.
func dummyStationsF() -> Future<[Station]> {
return future {
let expected12StSt = Station(name: "12th St. Oakland City Center", abbreviation: "12th", city: "Oakland", latitude: 37.803664, longitude: -122.271604)
let expected16StSt = Station(name: "16th St. Mission", abbreviation: "16th", city: "San Francisco", latitude: 37.765062, longitude: -122.419694)
let expectedMontSt = Station(name: "Montgomery St.", abbreviation: "mont", city: "San Francisco", latitude: 37.789256, longitude: -122.401407)
let expectedRockSt = Station(name: "Rockridge", abbreviation: "rock", city: "Oakland", latitude: 37.844601, longitude: -122.251793)
let expectedSFOSt = Station(name: "San Francisco Int'l Airport", abbreviation: "sfia", city: "San Francisco Int'l Airport", latitude: 37.616035, longitude: -122.392612)
let expectedSSFSt = Station(name: "South San Francisco", abbreviation: "ssan", city: "South San Francisco", latitude: 37.664174, longitude: -122.444116)
let stns = [expected12StSt,expected16StSt,expectedMontSt,expectedRockSt,expectedSFOSt,expectedSSFSt]
return Result.Success(Box(stns))
}
}
func dummyAbbrDictF() -> Future<Dictionary<String, Station>> {
return self.dummyStationsF().map { stations -> Dictionary<String, Station> in
var dict: Dictionary<String, Station> = [:]
for station in stations {
dict[station.abbreviation] = station
}
return dict
}
}
I also put all the code into a branch https://github.com/firemuzzy/BartApp, the 'testAbbrs' test in StationStoreTests is failing due the issue of the map function getting stuck.
I wanted to add BrightFutures to my OSX project using cocoapods. But for some reason it won't let me install it.
My Podfile
platform :osx, '10.8'
use_frameworks!
pod 'BrightFutures', '~> 2.0.1'
$ pod install --verbose
Preparing
Updating local specs repositories
Updating spec repo `master`
$ /usr/local/bin/git pull --ff-only
Already up-to-date.
Analyzing dependencies
Inspecting targets to integrate
Using `ARCHS` setting to build architectures of target `Pods`: (``)
Resolving dependencies of `Podfile`
[!] Unable to satisfy the following requirements:
- `BrightFutures (~> 2.0.1)` required by `Podfile`
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/resolver.rb:388:in `handle_resolver_error'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/resolver.rb:69:in `rescue in resolve'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/resolver.rb:56:in `resolve'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/installer/analyzer.rb:535:in `block in resolve_dependencies'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/user_interface.rb:59:in `section'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/installer/analyzer.rb:533:in `resolve_dependencies'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/installer/analyzer.rb:70:in `analyze'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/installer.rb:209:in `analyze'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/installer.rb:131:in `block in resolve_dependencies'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/user_interface.rb:59:in `section'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/installer.rb:130:in `resolve_dependencies'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/installer.rb:103:in `install!'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/command/project.rb:71:in `run_install_with_update'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/command/project.rb:101:in `run'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/claide-0.9.1/lib/claide/command.rb:312:in `run'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/lib/cocoapods/command.rb:48:in `run'
/usr/local/var/rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/cocoapods-0.38.1/bin/pod:44:in `<top (required)>'
/usr/local/var/rbenv/versions/2.1.2/bin/pod:23:in `load'
/usr/local/var/rbenv/versions/2.1.2/bin/pod:23:in `<main>'
Hi @Thomvis
I created a playground and a pull request. Let me know if that's something you'd be interested in. More info in the pull request itself.
I'm talking about something like the following:
func join<A>(future: Future<Future<A>>) -> Future<A> {
return future.flatMap{$0}
}
This is probably straying a bit into RAC's territory, but is there a way to send multiple values over time to a Future? My use case is the CLLocationManager's delegate API, where things like authorisation can return indeterminate states before returning a proper value.
I'd prefer not to have to use some kind of "retry" mechanism, but I get this might not be the point of BF.
I'm having trouble deciphoering an error, and it's listed in my code (rather than a BrightFutures file) so probably it's my own bug, but in case it's meaningful I wanted to post here (and perhaps you'll have seen something like this before?)
function signature specialization <Arg[0] = Owned To Guaranteed, Arg[1] = Owned To Guaranteed, Arg[2] = Owned To Guaranteed> of MyPackage.MyFile.myFunction (MyFile.myFunction)(ObjectiveC.NSMutableDictionary, then : () -> ()) -> () (MyFile.swift:1562)
Hi @Thomvis
I was wondering if you would consider supporting semantic versioning in the future for better Carthage support?
https://github.com/Carthage/Carthage#tag-stable-releases
While I use the carthage to check out the master branch, it would be nice to indicate a tag. (Specific version) Perhaps consider this after 1.0.0 release (?) as I wouldn't want you to change the current tag scheme that you have now.
The current head of swift-2.0 is stable, but the changelog and migration guide need updating.
I use BrightFutures with Alamofire
I write extension for Alamofire.Request.
request.responseJSONPromise()
run with no error.
However, when I chain Future
using flatMap
, Xcode7 shows a compile error message.
Here's my code
public func getToken(username username: String, password: String) -> Future<String, DRCloudServerError> {
let request = Alamofire.request( .POST, url, parameters: params)
return request.responseJSONPromise().flatMap{ json -> Future<String, DRCloudServerError> in
let promise = Promise<String, DRCloudServerError>()
if let accessToken = json["access_token"].string{
promise.trySuccess(accessToken)
}else{
promise.tryFailure(DRCloudServerError.JSONParseError)
}
return promise.future
}
}
and my Alamofire.Request extension
extension Alamofire.Request{
func responseJSONPromise() -> Future<JSON,DRCloudServerError>{
let promise = Promise<JSON, DRCloudServerError>()
responseJSON{ request, response, result in
if let error = self.handleStatusCodeError(response, data: result.data){
promise.tryFailure(error)
}
switch(result){
case let .Failure(_, error):
let errorDescription = "\(error)"
promise.tryFailure(DRCloudServerError.RequestError(errorDescription))
case let .Success(value):
let json = JSON(value)
promise.trySuccess(json)
}
}
return promise.future
}
}
Say I have a long-running background calculation, that the user should be able to cancel. The current implementation does not include some communication mechanism for signalling this event. How could such a feature be implemented? I think the following concerns should be addressed:
So far I'm seeing this is not possible. I'm looking for a way to replace callback logic where the callback is executed 2 times.
The reason I have this is a webservice call with a local-database cache. I always return to the caller the result of the local database and do webservice call in the background. If the result of the webservice call is different from the result which I returned from the local db, I return this result (again) to the caller. So my callback can be executed 1 or 2 times. The idea is to show the cached result to the client as soon as possible, and if there's a change in the remote data to refresh the UI immediately with it.
Previously I had (roughly) something like:
func myCall(handler: (MyResult) -> ()) {
getFromLocalDB {localDBResult in
handler(localDBResult)
}
getFromRemote {remoteResult
//...
if remoteResult != localDBResult {
handler(remoteResult)
}
}
This is what I came up as replacement using futures (I have little experience with futures, maybe there's a better way):
func myCall() -> Future<MyResult, NSError> {
let promise = Promise<MyResult, NSError>()
getFromLocalDB.onComplete {result in
// ...
promise.success(localDBResult)
}
getFromRemote.onComplete {result
// ...
if remoteResult != localDBResult {
promise.success(remoteResult)
}
return promise.future
}
But this causes an assertion error on the second success call because the future is already completed.
I came up with a solution in which I return 2 futures, like this:
func myCall() -> (cached: Future<MyResult, NSError>, remote: Future<MyResult, NSError>) {
let promiseCached = Promise<MyResult, NSError>()
let promiseRemote = Promise<MyResult, NSError>()
getFromLocalDB.onComplete {result in
// ...
promiseCached.success(localDBResult)
}
getFromRemote.onComplete {result
// ...
if remoteResult != localDBResult {
promiseRemote.success(remoteResult)
}
return (cached: promiseCached.future, remote: promiseRemote.future)
}
And handle with a common closure:
let completion: Result<[MyResult], NSError> -> () = {result in
// ...
}
let (cached: Future<[MyResult], NSError>, remote: Future<[MyResult], NSError>) = getMyResults()
cached.onComplete { // this additional closure is necessary - somehow it was not possible to pass the completion closure directly
completion($0)
}
remote.onComplete {
completion($0)
}
And that works, but I wonder if there's a better way. Having the handler callback called twice is maybe not the cleanest way to implement this, but there may be other scenarios with a callback-similar setup which has to be called multiple times.
Hey there, I'm using BrightFutures as a dependency in Spine and I'm getting the following when compiling:
Ld /Users/kurko/Library/Developer/Xcode/DerivedData/Dinero-frfqupqfiefqgtevsufnmfrmbtcl/Build/Products/Debug-iphonesimulator/Spine.framework/Spine normal x86_64
cd /Users/kurko/www/ios/Dinero/Pods
export IPHONEOS_DEPLOYMENT_TARGET=8.0
export PATH="/Applications/Xcode7.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode7.app/Contents/Developer/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Applications/Xcode7.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch x86_64 -dynamiclib -isysroot /Applications/Xcode7.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator9.0.sdk -L/Users/kurko/Library/Developer/Xcode/DerivedData/Dinero-frfqupqfiefqgtevsufnmfrmbtcl/Build/Products/Debug-iphonesimulator -F/Users/kurko/Library/Developer/Xcode/DerivedData/Dinero-frfqupqfiefqgtevsufnmfrmbtcl/Build/Products/Debug-iphonesimulator -filelist /Users/kurko/Library/Developer/Xcode/DerivedData/Dinero-frfqupqfiefqgtevsufnmfrmbtcl/Build/Intermediates/Pods.build/Debug-iphonesimulator/Spine.build/Objects-normal/x86_64/Spine.LinkFileList -install_name @rpath/Spine.framework/Spine -Xlinker -rpath -Xlinker @executable_path/Frameworks -Xlinker -rpath -Xlinker @loader_path/Frameworks -mios-simulator-version-min=8.0 -Xlinker -objc_abi_version -Xlinker 2 -fobjc-arc -fobjc-link-runtime -L/Applications/Xcode7.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator -Xlinker -add_ast_path -Xlinker /Users/kurko/Library/Developer/Xcode/DerivedData/Dinero-frfqupqfiefqgtevsufnmfrmbtcl/Build/Intermediates/Pods.build/Debug-iphonesimulator/Spine.build/Objects-normal/x86_64/Spine.swiftmodule -framework BrightFutures -framework Foundation -framework SwiftyJSON -single_module -current_version 1 -Xlinker -dependency_info -Xlinker /Users/kurko/Library/Developer/Xcode/DerivedData/Dinero-frfqupqfiefqgtevsufnmfrmbtcl/Build/Intermediates/Pods.build/Debug-iphonesimulator/Spine.build/Objects-normal/x86_64/Spine_dependency_info.dat -o /Users/kurko/Library/Developer/Xcode/DerivedData/Dinero-frfqupqfiefqgtevsufnmfrmbtcl/Build/Products/Debug-iphonesimulator/Spine.framework/Spine
Undefined symbols for architecture x86_64:
"direct generic type metadata pattern for Result.Result", referenced from:
ext.Spine.BrightFutures.Future<A, B where B: Swift.ErrorType>.onServerFailure <A, B where B: Swift.ErrorType> (BrightFutures.Future<A, B>)((B) -> ()) -> BrightFutures.Future<A, B> in FutureExtensions.o
ext.Spine.BrightFutures.Future<A, B where B: Swift.ErrorType>.onNetworkFailure <A, B where B: Swift.ErrorType> (BrightFutures.Future<A, B>)((B) -> ()) -> BrightFutures.Future<A, B> in FutureExtensions.o
ext.Spine.BrightFutures.Future<A, B where B: Swift.ErrorType>.onClientFailure <A, B where B: Swift.ErrorType> (BrightFutures.Future<A, B>)((B) -> ()) -> BrightFutures.Future<A, B> in FutureExtensions.o
"protocol witness table for <A, B where B: Swift.ErrorType> Result.Result<A, B> : Result.ResultType in Result", referenced from:
ext.Spine.BrightFutures.Future<A, B where B: Swift.ErrorType>.onServerFailure <A, B where B: Swift.ErrorType> (BrightFutures.Future<A, B>)((B) -> ()) -> BrightFutures.Future<A, B> in FutureExtensions.o
ext.Spine.BrightFutures.Future<A, B where B: Swift.ErrorType>.onNetworkFailure <A, B where B: Swift.ErrorType> (BrightFutures.Future<A, B>)((B) -> ()) -> BrightFutures.Future<A, B> in FutureExtensions.o
ext.Spine.BrightFutures.Future<A, B where B: Swift.ErrorType>.onClientFailure <A, B where B: Swift.ErrorType> (BrightFutures.Future<A, B>)((B) -> ()) -> BrightFutures.Future<A, B> in FutureExtensions.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
I saw other issues here with the same problem and it seems like setting Result
explicitly in the Podfile would solve it, but it doesn't for me. Here's my Podfile.lock:
PODS:
- Alamofire (3.0.1)
- BrightFutures (3.0.0):
- Result (= 0.6.0-beta.4)
- Realm (0.96.1):
- Realm/Headers (= 0.96.1)
- Realm/Headers (0.96.1)
- RealmSwift (0.96.1):
- Realm (= 0.96.1)
- Result (0.6.0-beta.4)
- Spine (0.2):
- BrightFutures (~> 3.0)
- SwiftyJSON (~> 2.3.0)
- SwiftyJSON (2.3.0)
DEPENDENCIES:
- Alamofire (~> 3.0)
- RealmSwift
- Spine (from `https://github.com/kurko/Spine.git`, tag `swift-2.0`)
EXTERNAL SOURCES:
Spine:
:git: https://github.com/kurko/Spine.git
:tag: swift-2.0
CHECKOUT OPTIONS:
Spine:
:git: https://github.com/kurko/Spine.git
:tag: swift-2.0
SPEC CHECKSUMS:
Alamofire: 2457e1b2e6c46bb05c3a598c542b7bfd08893775
BrightFutures: 4a3f46747e5633562bdcef55c9e291bfb7288c34
Realm: d05e4621f67fb1c36acd4e573ac5b52a407fc2cc
RealmSwift: 6c96a72b385027d9593b69f6821c697fe843eb68
Result: f7927152cbaec0c043abb06ba0bc432678818418
Spine: f3414766a0e500dc150b838af6663288890495ce
SwiftyJSON: 8d6b61a70277ef2a5d710d372e06e7e2d87fb9e4
COCOAPODS: 0.39.0
Any idea what it could be? Seems like it's either BrightFutures or Result.
Maybe I'm missing something here, but it seems like I must specify the return type of the closure passed to flatMap
. When I use just the parameters, it fails to build with error: "Missing argument for parameter 'f' in call".
Doesn't work:
Artist.findOne("1").flatMap { resource, meta in
return resource.findRelated("albums")
}
Does work:
Artist.findOne("1").flatMap { resource, meta -> Future<([Resource], Meta?)> in
return resource.findRelated("albums")
}
It would be nice to have Carthage support. Since Carthage doesn't support semver with extra labels added, we need an intermediate release for that. Also, the scheme must be marked as shared.
As pointed out by #44, the documentation is still referring to FutureUtils. This class is gone now.
I keep seeing this compile crashes:
Undefined symbols for architecture x86_64:
"direct generic type metadata pattern for Result.Result", referenced from:
type metadata accessor for Result.Result<Swift.String, BrightFutures.NoError> in Track.o
"protocol witness table for <A, B where B: Swift.ErrorType> Result.Result<A, B> : Result.ResultType in Result", referenced from:
static UpshotCore.Track.(demographicData in _355BED5052E6A82D51CFE2CBBD95410A) (UpshotCore.Track.Type)(Swift.String) -> () in Track.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Even when I'm just using test code:
func doStuff() -> Future<String, NoError> {
let promise = Promise<String, NoError>()
promise.success("hi")
return promise.future
}
I'm currently updating my app for Swift 2.0, but can't get my app to run with any of the Swift 2.0 branches using Carthage.
I was able to (after some hacking) get the "swiftier-2.0" branch to build with Carthage, but I kept getting a fatal error whenever I would call onSuccess
Is there a way to run a set of promises simultaneously with this library?
Is it possible to use InvalidationTokens with .flatMap()
?
Hi,
Just start using BrightFutures and it's really fun! Thanks for the work done :)
I have a question, recently hit this patter two times:
future {
//Do some computation
return Result(value: successValue)
}.flatMap { goodValue in
if goodValue.holdSomeCondition() {
return doSomethingElse()
} else {
return Future(value: goodValue)
}
}
The question is, how can I avoid the flatMap
when the condition isn't true? I found filter
but if the condition is false the operation fail. I could do the filter
and handle the error but I don't like it much.
Thanks
The v2.0.0-beta.2 tag has wrong version in podspec: s.version = '2.0.0-beta.1'
So it doesn't seem to be possible to install beta 2 via pods. (Note that using direct git reference in pods doesn't help - this also installs beta 1:
pod 'BrightFutures', :git => 'https://github.com/Thomvis/BrightFutures.git', :tag => 'v2.0.0-beta.2')
var allFutures = [future1, future2]
FutureUtils.sequence(allFutures).onSuccess { result in
println("complete")
}
When attempting to use FutureUtils class like above, I get the following error:
Use of unresolved identifier 'FutureUtils'
Looks like the FutureUtils functions were turned into free functions here: 17d4f21. But when I change my code to a "free function":
var allFutures = [future1, future2]
sequence(allFutures).onSuccess { result in
println("complete")
}
I get this error:
Cannot invoke 'onSuccess' with an argument list of type '((_) -> _)'
Any ideas of how to use the FutureUtils functions? Also, the documentation needs to be updated regarding the FutureUtils methods.
Hello,
We would like to have a more functional notification mechanism due to the following problems in current IOS Notification system:
Both notification and futures let user register future events and handlers, so at least conceptually it seems like a natural extension for futures to handle such use case. The main obstacle for the current BrightFutures implementation is the assumption that future is only executed once, any subsequent completion/callback attempts are treated as illegal state. If this behavior can be configured or allow subclass to override, we should be able to use this persistent future to model the notification use case...
thoughts, concerns or gotcha?
I'm trying to perform a background operation using BrightFutures. The result (MKPolyline) should be displayed in a MKMapView; thus the callback should be performed on the main thread. However the callbackExecutionQueue
results in an extra dispatch queue on top of the main queue. This results in EXC_BAD_ACCESS when the MKPolyline is added to the MapView. When the highlighted line is removed, everything works as expected.
Simplified usage:
future(context: Queue.global) { () -> Result<MKPolyline> in
return Result(polyline)
}
.onSuccess(context: Queue.main) { polyline in
self.mapView.addOverlay(polyline)
}
It would be great if there would be a Gitter room for BrightFutures
I have the following:
func promiseProvider() -> Future<User> {
let promise = Promise<User>()
promiseHandler(promise)
return promise.future
}
func promiseHandler<T>(aPromise: T) {
// do something with he promise:
promise.success(User())
}
I'm basically trying to pass the promise I created in PromiseProvider
to another method (promiseHandler
). But for whatever reason, Swift complains:
Cannot invoke 'promiseHandler' with an argument list of type '(Promise<User>)'
Any help would be appreciated, thanks!
Just updated to v3.0.0-beta.1
and Carthage builds, but emits the following error:
ld: warning: -weak_framework is treated as -framework when used with -bitcode_bundle (Xcode setting ENABLE_BITCODE=YES). Weak linking may still happen based on availability mark-up in headers
It looks like Queue
only exposes a mechanism for creating queues that are DISPATCH_QUEUE_SERIAL
.
Is there a reason you decided not to include a way to create a concurrent (DISPATCH_QUEUE_CONCURRENT
) queue directly?
Hi,
I'm having a lot of issues handling the error type when composing futures.
Typically:
let three: Future<Int, NoError> = future(3)
let fut: Future<Int, NSError> = future { //long computation that can fail }
let composed =fut.flatMap { _ in three)
Produces an compile error. But it all works when both futures have the same Error Type.
I expected composed
to be of type Future<Int, NSError>
because one of the error type is a Void type, only the other one makes sense.
If both types conform to ErrorType
then I would expect a generic ErrorType
on which I can patten match or a composed error (like a tuple of optional errors).
Is there a way of achieving this behaviour? Is it intended? Am I doing something wrong?
Hello.
When using BrightFutures 3.0.0 I'm unable to upload the .ipa to iTunes Connect. It looks like its because of a dependency to Result<0.6.0-beta.4> which makes the transporter freak out.
[15:39:57]: [Transporter Error Output]: ERROR ITMS-90060: "This bundle is invalid. The value for key CFBundleShortVersionString '0.6.0-beta.4' in the Info.plist file must be a period-separated list of at most three non-negative integers."
Is it possible to use a released version instead? :)
Hello @Thomvis! Great project! I love the simplicity and how the code works. However, I didn't notice anything in the documentation that would allow for promises chaining like they have in PromiseKit. I also looked at the code as well. The andThen() function only supports side effects and not the same idea as chaining promises and I didn't see anything else in the code that would support that functionality.
Is there something I missed or is promises chaining not part of the design of BrightFutures? Or maybe it's something that's part of the roadmap? Thanks.
Trying to pass a tuple to Promise#success
and getting hit with a compiler warning stating
Missing argument for parameter #2 in call
Code to re-produce the error:
var promise = Promise<(Int, String)>()
promise.success( (1, "hello") )
I'm sure its a problem with the compiler. Tried in Xcode 6.0.1 and 6.1. Thought I would let you know though.
When using BrightFutures together with other libraries that implement a Box to work around the enum limitations, it can be confusing to have multiple Box
types in your codebase. I would suggest using robrix/Box, since that seems to become the standard micro-framework to use for solving this problem.
Hello @Thomvis
Just wanted to let you know that the Cocoapods main repo still has 1.0 beta 2 as the latest version. In case if other users of the pod don't know there's a new updated version.
while there are flatMap to chain futures for successful results, what is the best way to do retry kind of logic when there is failure? i.e. how do we chain futures for failure path?
In my project find useful to chain multiple futures:
let f = service.create(user, password: user.password).chain { user in
return self.service.login(user.email, user.password)
}
Both the service request returns a Future type.
I created this extension that might be useful to others:
extension Future {
func chain<U> (f: (T)-> Future<U> ) -> Future<U> {
let p = Promise<U>()
self.onComplete { result in
switch result{
case .Success(let boxedFuture):
let future = f(boxedFuture.value)
future.onSuccess { value in
p.success(value)
}
future.onFailure{ err in
p.failure(err)
}
break
case .Failure(let e):
p.failure(e)
break
}
}
return p.future
}
}
In Xcode Beta 6, compiling BrightFutures gives the following error:
'__conversion' functions are no longer allowed
It looks like there is not another way to do an implicit type conversion to workaround the .Success value in the TaskResult enum. Unfortunately, writing the code as it should be written:
public enum TaskResult<T> {
case Success(T)
case Failure(NSError)
...
}
still results in an "unimplemented IR generation feature non-fixed multi-payload enum" error.
I think it is necessary to expose the unboxing of the generic value to users of the API, but I didn't want to make a pull-request in case you had a good solution.
Your podspec includes:
s.dependency 'Result', '0.6-beta.1'
Unfortunately this is causing newer frameworks (such as ReactiveCocoa, Swift 2 branch), Moya, and others to break:
dyld: Library not loaded: @rpath/Result.framework/Result
Referenced from: /Users/zbeckman/Library/Developer/CoreSimulator/Devices/FCFAAFBF-1AB4-4223-9BCC-CA91CBDE96DC/data/Containers/Bundle/Application/9E7272D7-5C66-48F9-9E37-892E41662655/Glimpulse.app/Frameworks/ReactiveCocoa.framework/ReactiveCocoa
Reason: Incompatible library version: ReactiveCocoa requires version 1.0.0 or later, but Result provides version 0.6.0
(lldb)
Cocoapods doesn't work at all.
Carthage works but I can't add it to my project properly - it simply doesn't have "General tab" for binaries and etc. And so I can't simply include your library.
Could you advice another solution?
I get following 4 errors when compiling the latest master (6e4ca98) on XCode 6.1.1 / Swift 1.1
/Users/teemu/all/flancer/protos/BrightFutures/BrightFutures/FutureUtils.swift:63:33: error: missing argument for parameter 'f' in call
return zero.flatMap { zeroVal in
/Users/teemu/all/flancer/protos/BrightFutures/BrightFutures/Future.swift:261:24: error: missing argument for parameter 'callback' in call
self.onFailure { err in
^
/Users/teemu/all/flancer/protos/BrightFutures/BrightFutures/Future.swift:434:29: error: missing argument for parameter 'f' in call
return self.flatMap { thisVal -> Future<(T,U)> in
^
/Users/teemu/all/flancer/protos/BrightFutures/BrightFutures/Future.swift:442:29: error: missing argument for parameter 'f' in call
return self.flatMap { value -> Result<T> in
This issue is created to track the progress towards releasing a 1.0 version. Please chime in if you have any feedback or requests!
TODO:
Future.succeeded(..)
and f.succeeded()
(same goes for failed
) is confusing.f.completed({}, {})
(and in a lesser way in f.succeeded { }
and f.failed { }
adds enough value to justify its existence.Future
and TaskResult
have succeeded
, failed
and completed
(/handle
) methods, which seems duplicate.TaskResultValueWrapper
. Luckily, it is almost never exposed through public API.FutureUtils
functions from Scala have been ported over yetFuture
should be a pure functional future (two states: pending or complete), more like a 'task' (pending, complete, cancelled, succeeded, failed) or somewhere in betweenPostponed until after 1.0:
FutureUtils
should work on any SequenceType
, not only on Array
I'm on version 1.0.1
I have a protocol for some couchbase lite utilities
import Foundation
import BrightFutures
@objc protocol CouchUtilsProtocol {
var manager: CBLManager { get }
func indexUpdate(
databaseName: String,
designDocName: String,
viewName: String
) -> Future<Bool>
}
I have to add @objc
because I use dependency injection ('Typhoon', '3.1.7') on compilation I get:
Method cannot be marked @objc because its result type cannot be represented in objective-c
Is this a bug with BrightFutures Objective-C support not added fully etc (#12 confuses me a bit) or simply because Objective-c do not have generics ?
And/Or do I simply declare the protocol wrongly ~ a here and now work around are very welcome!
Now BrightFutures 3 has been released, it's time to think about what BrightFutures 4 could/should look like. I'd like to gather and track feedback from the community and my own idea's in this issue.
Candidate features:
Any other ideas?
Update: I've renamed the issue from "BrightFutures 4" to "BrightFutures 5", because of the near release of 4 that did not have the aforementioned goals.
I installed the pod using:
pod 'BrightFutures', :git => "https://github.com/Thomvis/BrightFutures.git"
when building the project I get:
(null): /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: unknown option character `X' in: -Xlinker
I'm using Xcode 6.1.1 (6A2008a)
For the time being I just embedded BrightFutures in my project, without cocoapods :-/
Anyone?
full error:
Libtool /Users/yelled3/Library/Developer/Xcode/DerivedData/Smore-bikwhdybmwziuicildyctmstzgwd/Build/Products/Debug-iphonesimulator/libPods-Smore-BrightFutures.a normal i386
cd /Users/yelled3/Development/smore-ios/Smore/Pods
export IPHONEOS_DEPLOYMENT_TARGET=8.0
export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -static -arch_only i386 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.1.sdk -L/Users/yelled3/Library/Developer/Xcode/DerivedData/Smore-bikwhdybmwziuicildyctmstzgwd/Build/Products/Debug-iphonesimulator -filelist /Users/yelled3/Library/Developer/Xcode/DerivedData/Smore-bikwhdybmwziuicildyctmstzgwd/Build/Intermediates/Pods.build/Debug-iphonesimulator/Pods-Smore-BrightFutures.build/Objects-normal/i386/Pods-Smore-BrightFutures.LinkFileList -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphonesimulator -Xlinker -add_ast_path -Xlinker /Users/yelled3/Library/Developer/Xcode/DerivedData/Smore-bikwhdybmwziuicildyctmstzgwd/Build/Intermediates/Pods.build/Debug-iphonesimulator/Pods-Smore-BrightFutures.build/Objects-normal/i386/Pods_Smore_BrightFutures.swiftmodule -framework Foundation -o /Users/yelled3/Library/Developer/Xcode/DerivedData/Smore-bikwhdybmwziuicildyctmstzgwd/Build/Products/Debug-iphonesimulator/libPods-Smore-BrightFutures.a
error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool: unknown option character `X' in: -Xlinker
Usage: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -static [-] file [...] [-filelist listfile[,dirname]] [-arch_only arch] [-sacLT] [-no_warning_for_no_symbols]
Usage: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool -dynamic [-] file [...] [-filelist listfile[,dirname]] [-arch_only arch] [-o output] [-install_name name] [-compatibility_version #] [-current_version #] [-seg1addr 0x#] [-segs_read_only_addr 0x#] [-segs_read_write_addr 0x#] [-seg_addr_table <filename>] [-seg_addr_table_filename <file_system_path>] [-all_load] [-noall_load]
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.