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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14864971/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 22:17:22  来源:igfitidea点击:

How do I create my own completion handler as part of method parameters

iosobjective-c

提问by user2070259

I want to create a completion handler for a certain class, instead of firing off the class's main code and waiting for a delegate callback. I've read through the Apple documentation and they don't seem to give a very good example of how to directly implement something like this.

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

回答by Chris C

You need to treat the completion block just like a variable. The method will accept a block as part of it's parameters, then store it for later.

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

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

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

You can typedef that block type for easier reading:

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

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

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

And then store your block as an instance variable:

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

In your @interface: CompletionBlock _block;

在您的@interface 中: CompletionBlock _block;

In the myMethod.. _block = [handler copy]

在我的方法.. _block = [handler copy]

Then when you want the completion block to execute you just call it like a regular block:

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

_block(myData, error);

_block(myData, error);

回答by Paul.s

If it was for an asynchronous method you could do it like this

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

- (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();
      }
    });
  });
}

this would be invoked with

这将被调用

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

Something to note is the guard to make sure that completionis pointing to something otherwise we will crash if we try to execute it.

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

Another way I often use blocks for completion handlers is when a viewController has finished and want's to be popped from a navigation stack.

我经常使用块作为完成处理程序的另一种方式是当 viewController 完成并希望从导航堆栈中弹出时。

@interface MyViewController : UIViewController

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

@end

@implementation MyViewController

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

@end

You would set the completion block when pushing this view onto the stack

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

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

回答by realtimez

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

Swift 2.2 语法

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)
}

回答by Peter

Chris C's answer is correct (and was very helpful to me) with one caveat:

Chris C 的回答是正确的(对我很有帮助),但有一个警告:

Placing the declaration CompletionBlock _block;in @interfaceis not thread safe.

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

Put CompletionBlock _block = [handler copy];in myMethod…instead if there is any possibility that myMethod…will be called from multiple threads (or dispatch queues).

CompletionBlock _block = [handler copy];myMethod…,而不是是否有任何可能myMethod…会从多个线程(或调度队列)被调用。

Thanks @Chris C.

谢谢@Chris C。