В Objective C, что эквивалентно передаче указателя на функцию в C? - PullRequest
27 голосов
/ 07 августа 2011
@implementation ThisObject

-(void)start {

       SomeOtherObject *someOtherObject = [SomeOtherObject alloc];

       [someOtherObject doSomethingAndCallThisFunctionWhenUrDone:myCallBackFunction :self];

}

-(void)myCallBackFunction {

       // :)

}

В принципе, как я могу заставить это работать?

Ответы [ 3 ]

58 голосов
/ 07 августа 2011

Существует четыре способа сделать обратный вызов:

  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];
    }
    
  2. Селекторы Вы можете использовать -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)];
    }
    
  3. Делегаты Используйте делегата.Это похоже на 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];
    }
    
  4. 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;

Обновление:

Я показал более подробно, как реализовать различные методы (см. Выше).

3 голосов
/ 07 августа 2011

Вы говорите об этом?

-(void)callSomePassedSelector:(SEL)callbackSelector {
    [someObjectThatRespondesToThisSelector performSelector:callbackSelector];
}

Я предполагаю, что вы хотите сохранить его и позвонить позже, но это должно дать вам всю необходимую информацию о том, как передать и позвонить. Существуют и другие способы вызова селектора, подробнее здесь

0 голосов
/ 07 августа 2011

Я немного озадачен тем, о чем ты говоришь, но так ли это?

[self performSelector:@selector(myCallFunction)];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...