クラスのメイン コードを起動してデリゲート コールバックを待機する代わりに、特定のクラスの完了ハンドラーを作成したいと考えています。Apple のドキュメントを読んだことがありますが、このようなものを直接実装する方法の非常に良い例を示しているようには見えません。
4 に答える
非同期メソッドの場合は、次のように実行できます
- (void)asynchronousTaskWithCompletion:(void (^)(void))completion;
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Some long running task you want on another thread
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) {
completion();
}
});
});
}
これはで呼び出されます
[self asynchronousTaskWithCompletion:^{
NSLog(@"It finished");
}];
注意すべき点は、それが何かを指していることを確認するためのガードcompletion
です。そうしないと、実行しようとするとクラッシュします。
完了ハンドラーにブロックをよく使用するもう1つの方法は、viewControllerが終了し、ナビゲーションスタックからポップしたい場合です。
@interface MyViewController : UIViewController
@property (nonatomic, copy) void (^onCompletion)(void);
@end
@implementation MyViewController
- (IBAction)doneTapped;
{
if (self.onCompletion) {
self.onCompletion();
}
}
@end
このビューをスタックにプッシュするときに、完了ブロックを設定します
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;
{
MyViewController *myViewController = segue.destinationViewController;
myViewController.onCompletion = ^{
[self.navigationController popViewControllerAnimated:YES];
};
}
変数のように完了ブロックを扱う必要があります。このメソッドは、ブロックをパラメーターの一部として受け入れ、後で使用できるように保存します。
- (void)myMethodWithCompletionHandler:(void (^)(id, NSError*))handler;
読みやすくするために、そのブロックの型を typedef できます。
typedef void (^CompletionBlock)(id, NSError*);
次に、ブロックをインスタンス変数として保存します。
あなたの @interface で:CompletionBlock _block;
myMethod で.._block = [handler copy]
次に、完了ブロックを実行する場合は、通常のブロックのように呼び出します。
_block(myData, error);