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

时间:2013-02-13 23:04:32

标签: ios objective-c

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

4 个答案:

答案 0 :(得分:34)

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

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

您可以输入该块类型以便于阅读:

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

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

在@interface中:CompletionBlock _block;

在myMethod .. _block = [handler copy]

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

_block(myData, error);

答案 1 :(得分: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();
      }
    });
  });
}

这将使用

调用
[self asynchronousTaskWithCompletion:^{
  NSLog(@"It finished");
}];

需要注意的是警卫要确保completion指向某些内容,否则我们会在尝试执行时崩溃。

我经常使用块来完成处理程序的另一种方法是当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];
  };
}

答案 2 :(得分:4)

以下是一个将String和完成处理程序作为变量的方法的示例。完成处理程序也可以接收String。

Swift 2.2语法

定义:

func doSomething(input: String, completion: (result: String) -> Void {
    print(input)
    completion(result: "we are done!")
}

调用该函数:

doSomething("cool put string!") { (result) in
        print(result)
}

答案 3 :(得分:0)

Chris C的回答是正确的(对我很有帮助),但有一点需要注意:

CompletionBlock _block;中放置声明@interface不是线程安全的。

如果有可能从多个线程(或调度队列)调用CompletionBlock _block = [handler copy];,请将myMethod…放在myMethod…中。

谢谢@Chris C。

相关问题