web-dev-qa-db-ja.com

Objective Cでは、Cで関数ポインタを渡すのと同じことは何ですか?

@implementation ThisObject

-(void)start {

       SomeOtherObject *someOtherObject = [SomeOtherObject alloc];

       [someOtherObject doSomethingAndCallThisFunctionWhenUrDone:myCallBackFunction :self];

}

-(void)myCallBackFunction {

       // :)

}

基本的に、どうすればこれを機能させることができますか?

29
Joe

コールバックを作成するには、次の4つの方法があります。

  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コールバックの推奨される方法は、ブロックを使用することです。これらは、iOS4.0以降またはMacOS X10.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;
_

更新:

さまざまな手法を実装する方法の詳細を示しました(上記を参照)。

59
rbrown

あなたはこれについて話しているのですか?

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

保存して後で呼び出すことをお勧めしますが、これにより、パスして呼び出す方法について必要なすべての情報が得られるはずです。セレクターを呼び出す方法は他にもあります。詳細を参照してください ここ

3
MByD

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

[self performSelector:@selector(myCallFunction)];
0
Jacob