NSDictionary に配置される JSON データをダウンロードできるライブラリを作成しました。このクラスを単純な Twitter エンジンでラップします。これにより、友人のタイムラインを取得し、更新を投稿し、GPS 位置情報を使用して更新を投稿できます。Objective-C に関する私の限られた経験から、すべてを接続する方法は委任を使用することです。非同期の結果をセレクターまたはメソッド シグネチャーにコールバックするデリゲート プロパティを設定しました。デリゲートでオプションまたは必須のインターフェイスを作成することもできます。これにより、Xcode がデリゲートの実装を少し支援できるようになります。Objective-C でデリゲートを使用する方法を学ぶために、この単純なプロジェクトを作成しました。
http://www.smallsharptools.com/downloads/ObjC/Delegates.zip
デリゲートでクラスを初期化できる Worker クラスを定義します。doWork メソッドで作業が完了すると、デリゲートのメソッド シグネチャが検索され、メッセージが返されます。次のコードを使用します。
if([[self delegate] respondsToSelector:@selector(workFinished:)]) {
NSString *msg = @"That's it? Easy!";
[[self delegate] workFinished:msg];
}
メッセージを返す workFinished: メソッドを探します。このメソッド シグネチャは、ヘッダーの Worker.h に次のコードを含むオプション インターフェイスとして宣言しました。
@protocol WorkerNotifications
@optional
- (void) workFinished: (NSString *) msg;
@end
すべての詳細については、ダウンロードからプロジェクトの残りの部分を確認できます。しかし、これら 2 つのコード スニペットは、この委任パターンがどのように機能するかを示しています。しかし、Twitter クラスでは、デリゲート メソッドへのコールバックにつながる非同期アクションを開始したメソッドのコンテキストを知る必要があります。呼び出し元のクラスから sendUpdate メソッドを複数回呼び出した場合、コールバックのコンテキストを知るにはどうすればよいですか?
通常、JavaScript、Java、C# などの言語では、開始コンテキストにアクセスできるインライン クロージャーまたは匿名クラスを作成しますが、現時点では iPhone の Objective-C ではそうではない可能性があります。この質問は、StackOverflow で既に尋ねられ、回答されていることがわかりました。
したがって、私が行ったことは、オプションのインターフェイスをスキップし、代わりに、非同期アクションが完了したときに Twitter クラスが呼び出すセレクターを渡したことです。このアクションを開始する呼び出しは次のようになります...
CMTwitterEngine *engine = [[CMTwitterEngine alloc] initWithDelegate:self];
[engine setSendUpdateFinished:@selector(sendUpdateFinished:)];
[engine setSendUpdateFailed:@selector(sendUpdateFailed:)];
[engine setParsingSendUpdateFailed:@selector(parsingSendUpdateFailed:)];
[engine setUsername:TWITTER_USERNAME pass:TWITTER_PASSWORD];
[engine sendUpdate:statusUpdateText.text];
このコードは、最初に self をデリゲートとしてエンジン参照を初期化します。セレクターで送信するコールバックをアタッチするために、sendUpdate メソッド シグネチャで元々持っていましたが、メソッド呼び出しがかなり長くなりました。単純にセレクターのプロパティを設定することにしました。これはすべて機能しますが、問題が部分的にしか解決されないため、これがどのように機能するかはわかりません。
この例を完成させるために、非同期作業を終了し、最終的に、指定されたセレクターを探して定義されている場合はそれを呼び出すメソッドを内部的に呼び出します。
- (void)sendUpdateFinished:(NSDictionary *)dictionary {
if (self.sendUpdateFinished != nil) {
[self.delegate performSelector:self.sendUpdateFinished withObject:dictionary];
}
}
ステータス メッセージを渡して Twitter の更新として送信することはできますが、発信元の呼び出しのコンテキストはまだわかりません。sendUpdate を複数回呼び出したいのに、最初の非同期呼び出しがまだ実行中の場合はどうすればよいですか? そして、2 番目の通話が最初に終了した場合はどうなるでしょうか。どちらもデリゲートとして自己を持つため、コンテキストを何らかの方法で追跡するか、別のセレクターに渡してそれらを区別する必要がありますが、これも私のニーズを満たしていません。非同期呼び出しが 3 つ、4 つ、または 5 つある場合はどうなりますか? どのメッセージが正常に送信され、いつ完了したかを知る必要があります。
これをすべて行う唯一の方法は、コンテキストに必要なすべてのプロパティを保持するクラスを作成し、そのクラスを非同期 Twitter メソッドへの呼び出しのデリゲートとして機能させ、親に報告することです。 UIViewController である可能性が高いクラス。私はこのアプローチを取りますが、このアプローチについて読んだり、これを行うサンプルコードを見たりしていません。
あなたならどうしますか?発信とは異なる順序で終了する可能性のある複数の非同期呼び出しをどのように処理し、完了時にコンテキストで処理しますか?