Существует четыре способа сделать обратный вызов:
Указатель функции Вы можете сделать указатель на функцию, если вы действительно хотите, но это не рекомендуется.Это делается так же, как вы делали бы это в 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 документы здесь .Вы можете сделать это так:
- (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];
}
Blocks Предпочтительным способом обратных вызовов является использование блоков.Они доступны только для 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;
Обновление:
Я показал более подробно, как реализовать различные методы (см. Выше).