web-dev-qa-db-ja.com

Objective-Cでコールバックを実行する方法

Objective-Cでコールバック機能を実行する方法は?

完成した例をいくつか見たいのですが、理解する必要があります。

117
ReachConnection

通常、Objective Cのコールバックはデリゲートで行われます。カスタムデリゲートの実装例を次に示します。


ヘッダーファイル:

@interface MyClass : NSObject {
    id delegate;
}
- (void)setDelegate:(id)delegate;
- (void)doSomething;
@end

@interface NSObject(MyDelegateMethods)
- (void)myClassWillDoSomething:(MyClass *)myClass;
- (void)myClassDidDoSomething:(MyClass *)myClass;
@end

実装(.m)ファイル

@implementation MyClass
- (void)setDelegate:(id)aDelegate {
    delegate = aDelegate; /// Not retained
}

- (void)doSomething {
    [delegate myClassWillDoSomething:self];
    /* DO SOMETHING */
    [delegate myClassDidDoSomething:self];
}
@end

これは一般的なアプローチを示しています。 NSObjectにコールバックメソッドの名前を宣言するカテゴリを作成します。 NSObjectは実際にこれらのメソッドを実装していません。このタイプのカテゴリは非公式プロトコルと呼ばれ、多くのオブジェクトがこれらのメソッドを実装する可能性があると言っています。これらは、セレクターの型シグネチャを前方宣言する方法です。

次に、「MyClass」のデリゲートになるオブジェクトがあり、必要に応じてMyClassがデリゲートのデリゲートメソッドを呼び出します。デリゲートコールバックがオプションの場合、通常は「if([delegate respondsToSelector:@selector(myClassWillDoSomething :))){」のようなものでディスパッチサイトでガードします。私の例では、両方のメソッドを実装するためにデリゲートが必要です。

非公式のプロトコルの代わりに、@ protocolで定義された正式なプロトコルを使用することもできます。その場合、デリゲートセッターのタイプとインスタンス変数を、単に「id」ではなく「id <MyClassDelegate>」に変更します。

また、デリゲートが保持されないことに気付くでしょう。これは通常、「MyClass」のインスタンスを「所有する」オブジェクトが通常デリゲートでもあるため行われます。 MyClassがデリゲートを保持した場合、保持サイクルが発生します。 MyClassインスタンスを持ち、デリゲートが弱いバックポインターであるため、そのデリゲート参照をクリアすることは、デリゲートであるクラスのdeallocメソッドでは良い考えです。それ以外の場合、MyClassインスタンスが存続している場合は、ぶら下がりポインターがあります。

93
Jon Hess

完全を期すために、StackOverflow RSSは質問をランダムに復活させたので、他の(新しい)オプションはブロックを使用することです:

@interface MyClass: NSObject
{
    void (^_completionHandler)(int someParameter);
}

- (void) doSomethingWithCompletionHandler:(void(^)(int))handler;
@end


@implementation MyClass

- (void) doSomethingWithCompletionHandler:(void(^)(int))handler
{
    // NOTE: copying is very important if you'll call the callback asynchronously,
    // even with garbage collection!
    _completionHandler = [handler copy];

    // Do stuff, possibly asynchronously...
    int result = 5 + 3;

    // Call completion handler.
    _completionHandler(result);

    // Clean up.
    [_completionHandler release];
    _completionHandler = nil;
}

@end

...

MyClass *foo = [[MyClass alloc] init];
int x = 2;
[foo doSomethingWithCompletionHandler:^(int result){
    // Prints 10
    NSLog(@"%i", x + result);
}];
135
Jens Ayton

以下は、デリゲートの概念を排除し、生のコールバックを行う例です。

@interface Foo : NSObject {
}
- (void)doSomethingAndNotifyObject:(id)object withSelector:(SEL)selector;
@end

@interface Bar : NSObject {
}
@end

@implementation Foo
- (void)doSomethingAndNotifyObject:(id)object withSelector:(SEL)selector {
    /* do lots of stuff */
    [object performSelector:selector withObject:self];
}
@end

@implementation Bar
- (void)aMethod {
    Foo *foo = [[[Foo alloc] init] autorelease];
    [foo doSomethingAndNotifyObject:self withSelector:@selector(fooIsDone:)];
}

- (void)fooIsDone:(id)sender {
    NSLog(@"Foo Is Done!");
}
@end

通常、メソッド-[Foo doSomethingAndNotifyObject:withSelector:]は非同期であるため、コールバックはここよりも便利になります。

49
Jon Hess

この質問を最新の状態に保つために、iOS 5.0の [〜#〜] arc [〜#〜] の導入は、これが Blocks を使用して達成できることを意味します簡潔に:

@interface Robot: NSObject
+ (void)sayHi:(void(^)(NSString *))callback;
@end

@implementation Robot
+ (void)sayHi:(void(^)(NSString *))callback {
    // Return a message to the callback
    callback(@"Hello to you too!");
}
@end

[Robot sayHi:^(NSString *reply){
  NSLog(@"%@", reply);
}];

Objective-Cのブロック構文を忘れた場合は、常に F **** ngブロック構文 があります。

8
Ryan Brodie

コールバック:Objective Cには4種類のコールバックがあります

  1. Selector type:NSTimer、UIPangestureがSelectorコールバックの例であることがわかります。非常に限られたコードの実行に使用されます。

  2. デリゲートタイプ:Apple framework。UITableViewDelegate、NSNURLConnectionDelegate。通常、多くのダウンロードを示すために使用されます。非同期的にサーバーからの画像など。

  3. NSNotifications:NotificationCenterは、イベントが発生したときに多くの受信者に通知するために使用されるObjective Cの機能の1つです。
  4. ブロック:ブロックはObjective Cプログラミングでより一般的に使用されます。これは素晴らしい機能であり、コードのチャンクを実行するために使用されます。チュートリアルを参照して理解することもできます: Blocks tutorial

他に答えがあれば教えてください。感謝します。

3
Anil Gupta