Подтвердить что ты не робот

Как создать собственный обработчик завершения как часть параметров метода

Я хочу создать обработчик завершения для определенного класса, вместо того, чтобы отключить основной код класса и ждать обратного вызова делегата. Я прочитал документацию Apple и, похоже, не очень хороший пример того, как напрямую реализовать что-то подобное.

4b9b3361

Ответ 1

Вам нужно обработать блок завершения так же, как переменную. Метод примет блок как часть его параметров, а затем сохранит его позже.

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

Вы можете напечатать этот тип блока для упрощения чтения:

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

И затем сохраните свой блок как переменную экземпляра:

В вашем @interface: CompletionBlock _block;

В myMethod.. _block = [handler copy]

Затем, когда вы хотите выполнить блок завершения, вы просто назовете его как обычный блок:

_block(myData, error);

Ответ 2

Если бы это был асинхронный метод, вы могли бы сделать это следующим образом:

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

Ответ 3

Вот пример метода, который берет String и обработчик завершения как переменные. Обработчик завершения также может получить строку.

Swift 2.2 Синтаксис

Defintion:

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

Вызов функции:

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

Ответ 4

Крис C ответ правильный (и был очень полезен для меня) с одной оговоркой:

Размещение объявления CompletionBlock _block; в @interface не является безопасным для потоков.

Поместите CompletionBlock _block = [handler copy]; в myMethod… вместо этого, если есть вероятность, что myMethod… будет вызван из нескольких потоков (или очередей отправки).

Спасибо @Chris C.