1. ホーム
  2. objective-c

[解決済み] Objective-Cでコールバックを実行する方法

2022-08-05 15:07:14

質問

Objective-Cでコールバック関数を実行するにはどうしたらよいでしょうか。

完成した例を見て、理解したいのですが。

どのように解決するのですか?

通常、オブジェクト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 <MyClassDelegate> の代わりに "とします。 id となります。

また、デリゲートが保持されていないことに気づかれるでしょう。これは通常、"MyClass" のインスタンスを所有するオブジェクトがデリゲートでもあるために行われるものです。もしMyClassがそのデリゲートを保持したら、retainサイクルが発生します。MyClassのインスタンスを持ち、そのデリゲートであるクラスのdeallocメソッドで、デリゲートの参照をクリアするのは良いアイデアです。そうしないと、何かが MyClass インスタンスを生かしている場合、ポインタがぶら下がったままになってしまうからです。