如何创建自己的完成处理程序作为方法参数的一部分

use*_*259 26 objective-c ios

我想为某个类创建一个完成处理程序,而不是触发该类的主代码并等待委托回调.我已经阅读了Apple文档,他们似乎没有给出一个很好的例子来说明如何直接实现这样的东西.

Chr*_*s C 34

您需要将完成块视为变量.该方法将接受一个块作为其参数的一部分,然后将其存储以供日后使用.

- (void)myMethodWithCompletionHandler:(void (^)(id, NSError*))handler;

您可以键入def那个块类型以便于阅读:

typedef void (^CompletionBlock)(id, NSError*);

然后将您的块存储为实例变量:

在你的@interface中: CompletionBlock _block;

在myMethod .. _block = [handler copy]

然后,当您想要执行完成块时,只需将其称为常规块:

_block(myData, error);


Pau*_*l.s 34

如果是异步方法,你可以这样做

- (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();
      }
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

这将被调用

[self asynchronousTaskWithCompletion:^{
  NSLog(@"It finished");
}];
Run Code Online (Sandbox Code Playgroud)

需要注意的是警卫要确保completion指向某些东西,否则如果我们尝试执行它就会崩溃.

我经常使用块来完成处理程序的另一种方法是当viewController完成并希望从导航堆栈弹出时.

@interface MyViewController : UIViewController

@property (nonatomic, copy) void (^onCompletion)(void);

@end

@implementation MyViewController

- (IBAction)doneTapped;
{
  if (self.onCompletion) {
    self.onCompletion();
  }
}

@end
Run Code Online (Sandbox Code Playgroud)

将此视图推入堆栈时,您将设置完成块

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;
{
  MyViewController *myViewController = segue.destinationViewController;
  myViewController.onCompletion = ^{
    [self.navigationController popViewControllerAnimated:YES];
  };
}
Run Code Online (Sandbox Code Playgroud)