处理异步操作可能会很繁琐。一般来说,有两种方法来进行这些操作:使用代码块和GCD(NSOperations也在此),以及使用代理。当代码执行很多这样的异步操作时,在某个点上代码会变得很难阅读。显然,同步代码更容易阅读和维护。这就是XAsync发挥作用的地方。它允许调用异步操作,并在异步操作完成之前暂停当前方法的进一步执行。它以非阻塞的方式实现,因此在异步操作执行时,调用者线程可以处理其他事件。
XAsync功能灵感来自于C#的await代码结构。
为Objective-C/Swift应用程序安装XAsync最容易且推荐的方式是使用CocoaPods进行安装和维护。
$ sudo gem install cocoapods
CocoaPods是用Ruby构建的,因此可以使用OS X上可用的默认Ruby进行安装。
$ cd <Path to Xcode project folder>
source 'https://github.com/CocoaPods/Specs.git'
platform :osx, '10.10'
use_frameworks!
target '<Put your Xcode target name here>' do
pod 'XAsync', '~>2.0'
end
$ pod install
您应该已经准备好一切。如果您在CocoaPods安装过程中遇到任何问题,请尝试在cocoapods.org中查找更多信息。
尽管XAsync以Objective-C作为其主要语言,但在Swift应用程序中仍然可以很容易地使用它。在按照安装部分所述安装XAsync后,需要执行以下操作
@import XAsync;
有关在同一个项目中使用Objective-C和Swift的更多信息,请参阅此处。
下面提供了在同步模式下使用XAsync功能的示例。
等待单个任务,没有任何结果
//...
@import XAsync;
//...
XAsyncTask *t1 = [XAsyncTask taskWithAction:^(XAsyncTask * __weak _Nonnull task) {
NSLog(@"Task 1 has been started.");
for (NSInteger i = 0; i < 1000000000; i++) {
}
NSLog(@"Task 1 is about to end.");
}];
NSLog(@"About to start async task 1.");
[t1 await];
NSLog(@"Async task 1 has been done.");
//...
//...
let t1 = XAsyncTask { (task) in
print("Task 1 has been started.")
for _ in 0..<1000000000 {
}
print("Task 1 is about to end.")
}
print("Task 1 is about to start.")
t1.await()
print("Task 1 has been done.")
//...
下面的例子展示了等待单个任务完成的示例,该任务期望返回一些结果
///...
XAsyncTask *t2 = [XAsyncTask taskWithAction:^(XAsyncTask * __weak _Nonnull task) {
NSLog(@"Task 2 has been started.");
NSInteger i = 0;
for (i = 0; i < 1000000000; i++) {
}
NSLog(@"Task 2 is about to end.");
task.result = [NSNumber numberWithInteger:i];
}];
NSLog(@"About to start async task 2.");
[t2 await];
NSLog(@"Async task 2 has been done with result: %@", [(NSNumber *)t2.result stringValue]);
///...
///...
let t2 = XAsyncTask { (task) in
print("Task 2 has been started.")
var i = 0
for _ in 0..<1000000000 {
i += 1;
}
print("Task 2 is about to end.")
task?.result = i;
}
print("Task 2 is about to start.")
t2.await()
print("Task 2 has been done with result: \(t2.result)")
///...
下面的例子展示了如何等待给定序列中的所有任务完成。任务将按照它们在初始序列中的顺序开始和完成。
///...
XAsyncTask *one_s = [XAsyncTask taskWithAction:^(XAsyncTask *__weak _Nullable task) {
NSLog(@"Sequence task 1 has been started.");
for (NSInteger i = 0; i < 100000000; i++) {
}
NSLog(@"Sequence task 1 is about to end.");
}];
XAsyncTask *two_s = [XAsyncTask taskWithAction:^(XAsyncTask *__weak _Nullable task) {
NSLog(@"Sequence task 2 has been started.");
for (NSInteger i = 0; i < 100000000; i++) {
}
NSLog(@"Sequence task 2 is about to end.");
}];
XAsyncTask *three_s = [XAsyncTask taskWithAction:^(XAsyncTask *__weak _Nullable task) {
NSLog(@"Sequence task 3 has been started.");
for (NSInteger i = 0; i < 100000000; i++) {
}
NSLog(@"Sequence task 3 is about to end.");
}];
NSLog(@"About to start sequence.");
[XAsyncTask awaitSequence:@[ one_s, two_s, three_s ]];
NSLog(@"Sequence has been finished.");
///...
///...
let one_s = XAsyncTask { (task) in
print("Sequence task 1 has been started.")
for _ in 0..<100000000 {
}
print("Sequence task 1 is about to end.")
}
let two_s = XAsyncTask { (task) in
print("Sequence task 2 has been started.")
for _ in 0..<100000000 {
}
print("Sequence task 2 is about to end.")
}
let three_s = XAsyncTask { (task) in
print("Sequence task 3 has been started.")
for _ in 0..<100000000 {
}
print("Sequence task 3 is about to end.")
}
print("About to start sequence.")
XAsyncTask.awaitSequence([one_s, two_s, three_s])
print("Sequence has been finished.")
///...
在一些情况下,只需要完成一定数量的任务,执行或完成顺序并不重要。重要的是所有任务都已经完成。在这种情况下,以下示例可能是有用的。
///...
XAsyncTask *one_all = [XAsyncTask taskWithAction:^(XAsyncTask *__weak _Nullable task) {
NSLog(@"Pool task 1 has been started.");
for (NSInteger i = 0; i < 100000000; i++) {
}
NSLog(@"Pool task 1 is about to end.");
}];
XAsyncTask *two_all = [XAsyncTask taskWithAction:^(XAsyncTask *__weak _Nullable task) {
NSLog(@"Pool task 2 has been started.");
for (NSInteger i = 0; i < 100000000; i++) {
}
NSLog(@"Pool task 2 is about to end.");
}];
XAsyncTask *three_all = [XAsyncTask taskWithAction:^(XAsyncTask *__weak _Nullable task) {
NSLog(@"Pool task 3 has been started.");
for (NSInteger i = 0; i < 100000000; i++) {
}
NSLog(@"Pool task 3 is about to end.");
}];
NSSet *poolAll = [NSSet setWithObjects:one_all, two_all, three_all, nil];
NSLog(@"About to start pool of tasks.");
[XAsyncTask awaitAll:poolAll];
NSLog(@"All tasks have been finished.");
///...
///...
let one_all = XAsyncTask { (task) in
print("Pool task 1 has been started.")
for _ in 0..<100000000 {
}
print("Pool task 1 is about to end.")
}
let two_all = XAsyncTask { (task) in
print("Pool task 2 has been started.")
for _ in 0..<100000000 {
}
print("Pool task 2 is about to end.")
}
let three_all = XAsyncTask { (task) in
print("Pool task 3 has been started.")
for _ in 0..<100000000 {
}
print("Pool task 3 is about to end.")
}
print("About to start all tasks' pool.")
XAsyncTask.awaitAll(Set(arrayLiteral: one_all, two_all, three_all))
print("All tasks have been finished.")
///...
在某些情况下,等待特定组中的至少一个任务完成可能很重要。以下示例说明。
///...
XAsyncTask *one_any = [XAsyncTask taskWithAction:^(XAsyncTask *__weak _Nullable task) {
NSLog(@"Pool task 1 has been started.");
for (NSInteger i = 0; i < 100000000; i++) {
}
NSLog(@"Pool task 1 is about to end.");
}];
XAsyncTask *two_any = [XAsyncTask taskWithAction:^(XAsyncTask *__weak _Nullable task) {
NSLog(@"Pool task 2 has been started.");
for (NSInteger i = 0; i < 100000000; i++) {
}
NSLog(@"Pool task 2 is about to end.");
}];
XAsyncTask *three_any = [XAsyncTask taskWithAction:^(XAsyncTask *__weak _Nullable task) {
NSLog(@"Pool task 3 has been started.");
for (NSInteger i = 0; i < 100000000; i++) {
}
NSLog(@"Pool task 3 is about to end.");
}];
NSSet *poolAny = [NSSet setWithObjects:one_any, two_any, three_any, nil];
NSLog(@"About to start a pool.");
[XAsyncTask awaitAny:poolAny];
NSLog(@"Waiting has been finished.");
///...
///...
let one_any = XAsyncTask { (task) in
print("Pool task 1 has been started.")
for _ in 0..<100000000 {
}
print("Pool task 1 is about to end.")
}
let two_any = XAsyncTask { (task) in
print("Pool task 2 has been started.")
for _ in 0..<100000000 {
}
print("Pool task 2 is about to end.")
}
let three_any = XAsyncTask { (task) in
print("Pool task 3 has been started.")
for _ in 0..<100000000 {
}
print("Pool task 3 is about to end.")
}
print("About to start a pool.")
XAsyncTask.awaitAny(Set(arrayLiteral: one_all, two_all, three_all))
print("Waiting has been finished.")
///...
如果一个需要完成的任务本身就是异步的,并且依赖于某些其他条件(例如,从服务获取响应),那么答案是:使用以下示例中所示的awaitSignal方法。
///...
XAsyncTask *ts = [XAsyncTask taskWithAction:^(XAsyncTask *__weak _Nonnull task) {
NSLog(@"Signal task has been started.");
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSInteger i = 0;
for (i = 0; i < 1000000000; i++) {
}
task.result = [NSNumber numberWithInteger:i];
[task fireSignal];
});
NSLog(@"Signal task is about to end.");
}];
NSLog(@"About to start signal task.");
[ts awaitSignal];
NSLog(@"Signal task has been done: %@", [(NSNumber *)ts.result stringValue]);
///...
///...
let ts = XAsyncTask { (task) in
print("Signal task has been started.");
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0)) {
var i = 0;
for _ in 0..<1000000000 {
i += 1
}
task?.result = i
task?.fireSignal()
}
print("Signal task is about to end.")
}
print("About to start signal task.")
ts.awaitSignal()
print("Signal task has been done: \(ts.result)")
///...
使用遵循MIT 许可协议。有关详细信息,请参阅LICENSE文件。