这是一个在 Objective-C 中实现 futures 的库,具有以下特点:
TOCFuture
表示最终结果,使用 TOCCancelToken
来传播取消通知,使用 TOCFutureSource
产生并控制最终结果,以及使用 TOCCancelTokenSource
产生并控制取消令牌。[TOCFuture futureWithResult:[TOCFuture futureWithResult:@1]]
自动转换为 [TOCFuture futureWithResult:@1]
。TOCCancelToken
取消变体的 until:
或 unless:
参数传递给操作。近期更改
方法 #1: CocoaPods
pod 'TwistedOakCollapsingFutures', '~> 1.0'
pod install
#import "CollapsingFutures.h"
在您想要使用 futures、取消令牌或它们的类别方法的地方方法 #2: 手动
#import "CollapsingFutures.h"
在您想要使用 futures、取消令牌或它们的类别方法的地方外部内容
使用 Future
以下代码是一个如何使TOCFuture
进行某种操作的示例。使用thenDo
在未来的成功时执行某些操作,并使用catchDo
在失败时执行某些操作(也有finallyDo
用于清理)。
#import "CollapsingFutures.h"
// ask for the address book, which is asynchronous because IOS may ask the user to allow it
TOCFuture *futureAddressBook = SomeUtilityClass.asyncGetAddressBook;
// if the user refuses access to the address book (or something else goes wrong), log the problem
[futureAddressBook catchDo:^(id error) {
NSLog("There was an error (%@) getting the address book.", error);
}];
// if the user allowed access, use the address book
[futureAddressBook thenDo:^(id arcAddressBook) {
ABAddressBookRef addressBook = (__bridge ABAddressBookRef)arcAddressBook;
... do stuff with addressBook ...
}];
创建一个Future
上面的示例中,asyncGetAddressBook
方法是如何控制返回的未来的?
在简单的情况下,即结果已经知道,您可以使用TOCFuture futureWithResult:
或TOCFuture futureWithFailure
。
当结果不是马上就知道时,使用类TOCFutureSource
。它有一个future
属性,在调用源对象的trySetResult
或trySetFailure
方法后完成。
这是asyncGetAddressBook
实现的示例
#import "CollapsingFutures.h"
+(TOCFuture *) asyncGetAddressBook {
CFErrorRef creationError = nil;
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, &creationError);
// did we fail right away? Then return an already-failed future
if (creationError != nil) {
return [TOCFuture futureWithFailure:(__bridge_transfer id)creationError];
}
// we need to make an asynchronous call, so we'll use a future source
// that way we can return its future right away and fill it in later
TOCFutureSource *resultSource = [FutureSource new];
id arcAddressBook = (__bridge_transfer id)addressBookRef; // retain the address book in ARC land
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef requestAccessError) {
// time to fill in the future we returned
if (granted) {
[resultSource trySetResult:arcAddressBook];
} else {
[resultSource trySetFailure:(__bridge id)requestAccessError];
}
});
return resultSource.future;
}
Future链式操作
创建和使用未来很有用,但正是像then:
和toc_thenAll
这样的转换方法赋予了它们强大的功能。它们既能消费也能生产未来的对象,使得连接复杂的异步序列看起来非常简单。
#import "CollapsingFutures.h"
+(TOCFuture *) sumOfFutures:(NSArray*)arrayOfFuturesOfNumbers {
// we want all of the values to be ready before we bother summing
TOCFuture* futureOfArrayOfNumbers = arrayOfFuturesOfNumbers.toc_thenAll;
// once the array of values is ready, add up its entries to get the sum
TOCFuture* futureSum = [futureOfArrayOfNumbers then:^(NSArray* numbers) {
double total = 0;
for (NSNumber* number in numbers) {
total += number.doubleValue;
}
return @(total);
}];
// this future will eventually contain the sum of the eventual numbers in the input array
// if any of the evetnual numbers fails, this future will end up failing as well
return futureSum;
}
一旦未来准备就绪,就设置转换发生的可能性,这使得您能够编写真正的异步代码,不阻塞宝贵的线程,并且很少需要样板代码和直观地传播失败。
如何构建
获取源代码:将这些git仓库克隆到您的机器上。
获取依赖项:安装cocoa pods。从项目目录中运行pod install
。
打开工作空间:使用XCode打开CollapsingFutures.xworkspace
(不是项目,而是工作空间)。运行测试并确认测试通过。