26

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

4

4 回答 4

34

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

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

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

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

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

在您的@interface 中:CompletionBlock _block;

在 myMethod.._block = [handler copy]

然后,当您希望完成块执行时,您只需像常规块一样调用它:

_block(myData, error);

于 2013-02-13T23:10:15.797 回答
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];
  };
}
于 2013-02-13T23:31:54.537 回答
4

Heres an example for a method that takes a String and a completion handler as variables. The completion handler can also receive a String.

Swift 2.2 Syntax

Defintion:

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

Calling the function:

doSomething("cool put string!") { (result) in
        print(result)
}
于 2016-07-30T09:52:23.363 回答
0
于 2016-04-21T18:07:42.940 回答