Ответ 1
Существует четыре способа сделать обратный вызов:
-
Указатель функций Вы можете сделать указатель на функцию, если хотите, но это не рекомендуется. Это было сделано так же, как и в C. Проблема заключается в том, что вы не можете использовать указатель на метод Objective-C. Это выглядит примерно так:
void callback(/* Some args */) { // Some callback. } - (void)doSomethingAndCallThisFunctionWhenDone:(void(*)(/* Some args */))func { // Do something. if (func) func(/* Some args */); } - (void)start { [self doSomethingAndCallThisFunctionWhenDone:&callback]; }
-
Селекторы. Вы можете использовать -performSelector:. Это выглядит так:
- (void)doSomethingAndCallTarget:(id)target withSelector:(SEL)sel { // Do something. [target performSelector:sel]; } - (void)start { SomeOtherObject * someOtherObject = [[SomeOtherObject alloc] init]; [self doSomethingAndCallTarget:someOtherObject withSelector:@selector(MyCallback)]; }
-
Делегаты. Используйте делегат. Это похоже на UITableViewDelegate/UITableViewDataSource. См. Apple docs здесь. Вы можете сделать это следующим образом:
- (void)doSomethingDelegate:(id<MyCallbackObject>)delegate { [delegate retain]; // Do something. [delegate performMyCallback]; // -performMyCallback must be declared in the MyCallbackObject protocol and implemented by SomeOtherObject. [delegate release]; } - (void)start { id<MyCallbackObject> someOtherObject = [[SomeOtherObject alloc] init]; [self doSomethingDelegate:someOtherObject]; [someOtherObject release]; }
-
Блоки. Предпочтительным способом для обратных вызовов является использование блоков. Они доступны только для iOS 4.0+ или Mac OS X 10.6+. Это выглядит примерно так:
- (void)doSomethingAndCallThisBlockWhenDone:(void(^)(/* Some args */))block { [block copy]; // Do something. if (block) block(/* Some args */); [block release]; } - (void)start { [self doSomethingAndCallThisBlockWhenDone:^void(/* Some args */){ // Return type and arguments may be omitted if you don't have any. // Your callback }]; }
Как вы можете видеть с блоком, его легче читать, а ваш обратный вызов встроен в ваш код. Это особенно приятно, поэтому вам не нужно выслеживать его. Есть еще много преимуществ блоков, но я не мог их охватить.
Последнее, если вы используете блок, вы захотите использовать typedef
, поэтому вам не нужно вводить непонятные типы блоков, такие как void(^)(/* Some args */)
все время. typedef
может выглядеть так:
typdef void(^MyCallback)(/* Some args */);
Затем вы можете объявить свой метод следующим образом:
- (void)doSomethingAndCallThisBlockWhenDone:(MyCallback)block;
Update:
Я показал более подробную информацию о том, как реализовать различные методы (см. выше).