この問題に対する別のアプローチとして、非同期タスクのヘルパー オブジェクトを作成し、タスクが呼び出されたときに完了ブロックをコピーするという方法があります。非同期タスクが終了したら、デリゲート メソッドを使用して完了ブロックを呼び出します。その結果、次のような順序でタスクを実行できます。
FSTask *taskA = [FSTask taskWithName:@"Task A"];
FSAsyncTask *taskB = [FSAsyncTask asyncTaskWithName:@"Task B"];
FSTask *taskC = [FSTask taskWithName:@"Task C"];
[taskA performTaskWithCompletionBlock:^ (NSString *result) {
NSLog(@"%@", result);
[taskB performTaskWithCompletionBlock:^ (NSString *result) {
NSLog(@"%@", result);
[taskC performTaskWithCompletionBlock:^ (NSString *result) {
NSLog(@"%@", result);
}];
}];
}];
では、これはどのように達成されるのでしょうか。さて、下のタスクオブジェクトを見てください...
FSTask.m -メイン スレッドでの同期作業 ...
@interface FSTask ()
@property (nonatomic, copy) NSString *name;
@end
@implementation FSTask
@synthesize name = _name;
+ (FSTask *)taskWithName:(NSString *)name
{
FSTask *task = [[FSTask alloc] init];
if (task)
{
task.name = name;
}
return task;
}
- (void)performTaskWithCompletionBlock:(void (^)(NSString *taskResult))block
{
NSString *message = [NSString stringWithFormat:@"%@: doing work on main thread ...", _name];
NSLog(@"%@", message);
if (block)
{
NSString *result = [NSString stringWithFormat:@"%@: result", _name];
block(result);
}
}
@end
FSAsyncTask.m -バックグラウンド スレッドでの非同期作業 ...
@interface FSAsyncTask ()
@property (nonatomic, copy) void (^block)(NSString *taskResult);
@property (nonatomic, copy) NSString *name;
- (void)performAsyncTask;
@end
@implementation FSAsyncTask
@synthesize block = _block;
@synthesize name = _name;
+ (FSAsyncTask *)asyncTaskWithName:(NSString *)name
{
FSAsyncTask *task = [[FSAsyncTask alloc] init];
if (task)
{
task.name = name;
}
return task;
}
- (void)performTaskWithCompletionBlock:(void (^)(NSString *taskResult))block
{
self.block = block;
// the call below could be e.g. a NSURLConnection that's being opened,
// in this case a NSURLConnectionDelegate method will return the result
// in this delegate method the completion block could be called ...
dispatch_queue_t queue = dispatch_queue_create("com.example.asynctask", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^ {
[self performAsyncTask];
});
}
#pragma mark - Private
- (void)performAsyncTask
{
for (int i = 0; i < 5; i++)
{
NSString *message = [NSString stringWithFormat:@"%d - %@: doing work on background thread ...", i, _name];
NSLog(@"%@", message);
[NSThread sleepForTimeInterval:1];
}
// this completion block might be called from your delegate methods ...
if (_block)
{
dispatch_async(dispatch_get_main_queue(), ^ {
NSString *result = [NSString stringWithFormat:@"%@: result", _name];
_block(result);
});
}
}
@end