Objective-Cでコールバック機能を実行する方法は?
完成した例をいくつか見たいのですが、理解する必要があります。
通常、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インスタンスが存続している場合は、ぶら下がりポインターがあります。
完全を期すために、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);
}];
以下は、デリゲートの概念を排除し、生のコールバックを行う例です。
@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:]は非同期であるため、コールバックはここよりも便利になります。
この質問を最新の状態に保つために、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ブロック構文 があります。
コールバック:Objective Cには4種類のコールバックがあります
Selector type:NSTimer、UIPangestureがSelectorコールバックの例であることがわかります。非常に限られたコードの実行に使用されます。
デリゲートタイプ:Apple framework。UITableViewDelegate、NSNURLConnectionDelegate。通常、多くのダウンロードを示すために使用されます。非同期的にサーバーからの画像など。
他に答えがあれば教えてください。感謝します。