4

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 で既に尋ねられ、回答されていることがわかりました。

Objective-Cでの匿名デリゲートの実装?

したがって、私が行ったことは、オプションのインターフェイスをスキップし、代わりに、非同期アクションが完了したときに 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 である可能性が高いクラス。私はこのアプローチを取りますが、このアプローチについて読んだり、これを行うサンプルコードを見たりしていません。

あなたならどうしますか?発信とは異なる順序で終了する可能性のある複数の非同期呼び出しをどのように処理し、完了時にコンテキストで処理しますか?

4

3 に答える 3

3

あなたの状況は NSNotificationCenter を使用するのに最適な場所だと思います

http://developer.apple.com/iphone/library/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html

于 2010-02-03T17:33:10.480 に答える
2

NSNotificationCenterがおそらくここで探しているものであるという以前に投稿された回答を2番目(または3番目)にする必要があります。

基本的に、発生した単一のアクションまたはイベントに応答してすべての代理人が何かを行う必要がある可能性がある場合は、通常、通知を使用します。これは、1対多の種類の委任またはオブザーバーパターンの実装と考えてください。知っておくべき基本的なことは次のとおりです。

  1. NSNotificationsには、NSStringだけである定義する名前があります。通知は名前で投稿でき、オブジェクトは名前で通知を受け取るように登録されます。

  2. 通知が投稿されると、notificationSenderオブジェクトやuserInfoディクショナリを提供できます。NotificationSenderは、受信者によって処理されているときに、特定の通知を誰が投稿したかを直接判断する方法です。userInfoは、通知とともに追加のコンテキスト情報を提供するために使用できるNSDictionaryです。

したがって、すべてのワーカーに非公式のプロトコルを採用させ、リフレクションスタイルの呼び出し(メソッド)をいじくり回すのではなく、実行時にワーカーのインスタンスをNSNotificationCenterに登録するだけです。通常、NSNotificationCenterへの登録は、各ワーカークラスのinitメソッドで行われます。各タイプのワーカーのインスタンスは、通常、NIBで「フリーズドライ」オブジェクトとして設定されるか、アプリデリゲートでプログラムによってインスタンス化できるため、アプリのライフサイクルの早い段階で通知センターに登録されます。

この問題が発生した場合、NSNotificationをNSNotificationCenter(基本にシングルトン)に投稿すると、その特定のタイプの通知を受信するために登録された他のすべてのものに、そのタイプの通知を処理するために指定されたメソッドが呼び出されます。これらのメソッドが完了すると、送信者に共通のメソッド(NSNotificationのオブジェクトメソッドを介して取得)を呼び出して、作業が完了したことを送信者に通知できます。

既知の各ワーカーが送信者の共通メソッドをチェックインすると、実行されるポストワーカー完了コードに進むことができます。

于 2010-02-03T19:24:21.430 に答える
1

考慮すべきことの 1 つは、代わりに通知を使用することです。コードを簡素化し、結合を緩くします。

于 2010-02-03T17:30:25.433 に答える