2011-08-07 37 views
21
@implementation ThisObject 

-(void)start { 

     SomeOtherObject *someOtherObject = [SomeOtherObject alloc]; 

     [someOtherObject doSomethingAndCallThisFunctionWhenUrDone:myCallBackFunction :self]; 

} 

-(void)myCallBackFunction { 

     // :) 

} 

基本上,我該如何做這項工作?在Objective C中,等價於在C中傳遞函數指針?

+0

但是這是什麼SomeOtherObject的一面呢?需要在SomeOtherObject中聲明什麼以及它需要做什麼? 它必須有一個doSomethingAndCallThisFunctionWhenUrDone。但是它實際上需要做什麼來調用對象ThisObject的所述方法? 目前爲止, – Joe

+0

我擴展了我的答案以顯示更多實施細節。對於函數指針和塊,你不需要一個對象來調用它們,但是你可以作爲參數傳遞對象。 – rbrown

回答

3

你在說這個嗎?

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

我假設你想存儲它並稍後調用它,但是這應該會給你所有關於如何傳遞和調用它所需的信息。還有其他的方法來調用選擇器,查看更多here

+0

你會怎樣通過選擇器呢? – TheJeff

0

我有點困惑你說什麼,但是這是它嗎?

[self performSelector:@selector(myCallFunction)]; 
49

有四種方法可以使一個回調:

  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 docs here。你可能不喜歡這樣:

    - (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. 的首選方法回調是使用塊。它們僅適用於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; 

更新:

我已經展示瞭如何實現不同的更詳細技術(見上文)。

+1

+1好綜合答案。請記住,如果您需要塊保留在不同的線程上或超出當前的runloop轉向,它需要被複制到堆中(或者您使用ARC進行編譯,並且它做的是正確的事情) –

+0

感謝戴夫。我忘了補充那個細節。它現在在那裏。 – rbrown