2011-08-07 6 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

あなたはこれについて話していますか?

これを保存して後で呼び出すことを前提にしていますが、これを渡して呼び出す方法についての必要な情報がすべて必要です。セレクタを呼び出す方法は他にもあります。詳しくはhere

+0

セレクタをどうやって渡しますか? – TheJeff

0

あなたが話していることについて少し混乱していますが、これはそれですか?

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

コールバックを行うための4つの方法があります:あなたは、あなたが本当にしたい場合は、関数ポインタを行うことができますが、それはお勧めできません

  1. 関数ポインタが。これは、Cで行うのと同じ方法で行われます。問題はObjective-Cメソッドへの関数ポインタを使用できないことです。それはこのようなものになります。あなたは-performSelectorを使用することができます

    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. セレクタを:.それは次のようになります。

    - (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を使用してコンパイルし、Right Thing™を実行する) –

+0

Thanks Dave。その詳細を追加するのを忘れてしまった。それは今そこにある。 – rbrown

関連する問題