22

すべてのViewControllerのダウンロードに使用するオブジェクトを作成しています。オブジェクトはシングルトンインスタンスであり、ダウンロードが完了すると、受信したデータを使用するコールバックメソッドがあります。また、ダウンロードが完了した後にコールバックするオブジェクトを認識できるように、デリゲートプロパティもあります。

この共有インスタンスを使用するコントローラーは複数あります。私の質問は、ダウンロードを要求した正しいビューコントローラーにコールバックする方法です。

私のアプローチは委任を使用することですが、問題は、他のView Controllerもその委任であるため、ダウンロードオブジェクトがすべてのオブジェクトにコールバックする可能性があり、これを追跡するのが難しいことです。

4

6 に答える 6

52

私は人々が複数の代表者を使おうとしたプロジェクトに取り組んできましたが、それは基本的に悪い考えです。デリゲートパターンは、クラスとそのデリゲートの間の約1対1の関係です。委任を切り替えて切り替えることで、ある程度の複数の委任を実現することは可能ですが、予期しない動作やバグが発生する可能性が高くなります。

私の推奨は、これについての考え方を変えることです。私が見ているように、2つのオプションがあります。

  1. メインクラスが対話できる複数のオブザーバーを登録できるオブザーバーパターンに切り替えます。これは、オブザーバーがすべて同じプロトコルを実装し、メインクラスがオブザーバーとそれらとの相互作用を認識したい場合に役立ちます。

  2. NSNotificationsをブロードキャストして、状態の変化とイベントを示します。メインクラスは誰が聞いているかを知る必要がなく、直接対話しないため、これはより分離されたアプローチです。他の人は、暇なときに通知を開始および停止できます。また、別のプロトコルを作成または実装する必要がないという利点もあります。代わりに、変更について知る必要のあるクラスをNSNotificationCenterに登録します。NSNotificationCenterは、通知のすべてのルーティングを処理します。

于 2012-10-08T03:15:26.363 に答える
14

実際には、デリゲートパターンがここでの最善のアプローチではないように思われます。

代わりに調べますNSNotificationCenter

基本的な考え方は、ネット接続を行うシングルトンがpostNotificationName:object:userInfo:、新しいデータが利用可能であることを示す通知を(のようなもので)投稿することです。この通知内で、userInfoフェッチしたデータを保持するディクショナリオブジェクト()、またはモデルのどの部分に更新されたデータが含まれているかに関する情報を渡すことができます。

次に、他のView Controllerは、を呼び出すことにより、これらの通知を「監視」するために自分自身を登録できますaddObserver:selector:name:object:。一般的に言って、vcが表示されるようになったときaddObserver、およびremoveObserverそれが非表示または遷移されたときに呼び出します。

幸運を!

于 2012-10-08T03:17:39.533 に答える
0

委任は、この問題に対する正しい解決策のようには思えません。要求しているViewControllerに、完了通知として呼び出すオブジェクト(自己)とセレクターを提供するように要求するのはどうですか?もちろん、ダウンロードが完了するまで、そのオブジェクトとセレクターを保存する場所が必要です。うまくいけば、このためのオブジェクトがあります(または作成できます)。

于 2012-10-08T03:46:01.000 に答える
0

これらの方法のいずれかを使用することをお勧めします

観察者:

他のオブジェクトに通知したいデータを使用する場合、プリミティブなデータに近いです。たとえば、「NSMutableArray」を使用している場合、標準の実装パターンではオブジェクトの1つの変更を通知できません。少なくとも、自分で実装する必要があります。それはそれほど再利用可能ではありません

通知

宛先オブジェクト(通知する必要がある)との対話が一方向である場合。これは、宛先オブジェクトからの確認応答やその他のデータが不要であることを意味します。

委任

各タイムステップで通知するオブジェクトが1つある場合。

注:成功と失敗のためのブロックの使用は、ネットワーク操作のようにデータがいつ終了または失敗するかわからないときに、キューに入れようとしているデータをブロードキャストするパターンではありません

編集: 通知を作成する方法| マルチデリゲートの問題と実装

于 2015-12-06T05:55:41.017 に答える
0

ここでの回答のほとんどに同意しますが、実際に複数のデリゲートを達成したい場合は、デリゲートの配列を宣言し、その配列内のすべてのデリゲートにメッセージを送信できる可能性があります。プロトコルにオプションのデリゲートメソッドがある場合は、呼び出す前に安全にチェックしてくださいresponds(to aSelector: Selector!) -> Bool(これらのデリゲートは配列で強く参照されるため、メモリ管理に注意してください)。繰り返しになりますが、複数のデリゲートはアーキテクチャ上の悪いアイデアである可能性が高く、ブロックまたは通知センターを使用する方がニーズに適していることに同意します。

于 2018-02-25T19:39:56.000 に答える
0

メッセージを転送するオブジェクトが他に1つしかない場合に有効なアプローチのひとつは、これを作成することです。forwardingDelegateこれにより、デリゲートのデバッグ順序が難しいという問題が発生することはなく、他のオブジェクトへの依存関係が不必要に作成されることもありません。多くのオブジェクトがある場合、これは最善のアプローチではない可能性があることに注意してください。これは主に1つの追加オブジェクト用ですが、SDKを受信して​​転送するオブジェクトがあれば、オブジェクトの配列をサポートするように拡張できます。他のオブジェクト[1]。転送されるオブジェクトによって使用されていない場合でも、転送されるオブジェクトに必要なすべてのメソッドは、それを渡す必要があることに注意してください。

たとえば、mapViewデリゲートからのメッセージを転送する必要がある場合:

 - (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated 
{
    // handle this object here. 

    if ([self.forwardingDelegate respondsToSelector:@selector(mapView:regionDidChangeAnimated:)])
    {
         [self.forwardingDelegate mapView:mapView regionDidChangeAnimated:animated];
    }

    // or handle this object here. 
}

[self.forwardingDelegate mapView:mapView regionDidChangeAnimated:animated];

転送プロパティは次のように宣言されます。

@property (nonatomic) id<MKMapViewDelegate> forwardingDelegate;

そして、他のオブジェクトは、元のメッセージを受信して​​いるかのようにプロトコルを採用します。

[1]他の投稿で言及されているように、デリゲートが呼び出される順序をあまり制御できないため、複数のデリゲートの配列アプローチは扱いにくい場合があります。

于 2019-12-12T06:35:29.233 に答える