2012-02-28 16 views
14

私はシングルトンであるNSObjectを持っています。このシングルトンクラスの代理人を持つことに問題はありますか?私はシングルトンタイプでは失敗すると心配しています。シングルトンオブジェクトの代理人

ここに私のシナリオがあります。私はAPIからNSDictionaryを引き出す非同期要求を行う関数(このシングルトンクラスの内部)を持っています。基本的にこのリクエストが完了したら、リクエストが完了したことをクラスに通知したいと思います。

+2

デリゲートが失敗するのはなぜですか?複数のリスナーに対して、代わりに 'NSNotificationCenter'を使用することを検討することができます。 –

+0

私は通知したいクラスが1つしかなく、質問文脈を – adit

答えて

30

いいえ、デリゲートが失敗し、代わりにNSNotificationCenterを使用することを検討していないでしょう。

static NSString *const kMyClassNotificationName = @"myClassNotificationName"; 

// where you would call a delegate method (e.g. [self.delegate doSomething]) 
[[NSNotificationCenter defaultCenter] postNotificationName:kMyClassNotificationName object:self userInfo: /* dictionary containing variables to pass to the delegate */]; 

// where you would set up a delegate (e.g. [Singleton instance].delegate = self) 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomething) name:kMyClassNotificationName object:[Singleton instance]]; 
+3

+1の 'NSNOtificationCenter'に+1してください。 – HelmiB

+1

@aditオブザーバー検索を高速化する必要がある場合は、NSNotificationCenter'の特別なインスタンスあなたのシングルトンで。その場合は、シングルトンの読み込み専用プロパティにして、オブザーバーが直接登録できるようにしてください。 – Costique

+3

これは本当に悪い形です。誰かが意図的にこのようなコードを書き留めるのはなぜですか?代理人やブロックを使った2つの優れたソリューションについては、vikingosegundoの回答をご覧ください。 – PostCodeism

17

あなたは基本的に3つのオプションがあります。

  • は、デリゲートを使用します。シネルトンはオブジェクトなので、代理人を持つことができます。複数のオブジェクトがそれを使用することを嫌っており、デリゲートとして自分自身を設定する必要がある場合、毎回それらをリセットすることができますが、それは髪の毛がかかってしまうかもしれません。

  • Richard J. Ross IIIさんのように通知を使用しますが、真剣に:あなたがシングルトンを持っている場合、私は一人の代議員に通知する必要がありますが、ブロードキャスト技術。

  • ブロックをシングルトンに渡し、シングルトンがタスクを完了すると実行される完了ブロックを使用します。 [NSURLConnection sendAsynchronousRequest:queue:completionHandler:]を参照してください(これはシングルトンではありませんが、クラスメソッドです。原則は同じです)。成功ブロックと失敗ブロックを使用する1つの完了ブロック、または偉大なAFNetworkingを使用します。シングルトンのデリゲートを持つことには何も問題はありません

    [[AFGowallaAPIClient sharedClient] getPath:urlString 
               parameters:mutableParameters 
                success:^(__unused AFHTTPRequestOperation 
                  *operation, 
                  id JSON) 
        { 
         NSMutableArray *mutableRecords = [NSMutableArray array]; 
         for (NSDictionary *attributes in [JSON valueForKeyPath:@"spots"]) { 
          Spot *spot = [[[Spot alloc] initWithAttributes:attributes] autorelease]; 
          [mutableRecords addObject:spot]; 
         } 
    
         if (block) { 
          block([NSArray arrayWithArray:mutableRecords]); 
         } 
        } failure:^(__unused AFHTTPRequestOperation *operation, NSError *error) { 
         if (block) { 
          block([NSArray array]); 
         } 
    }]; 
    
+3

評価者の皆様:誤植を修正するための投稿の編集は大丈夫です。しかし、私が知らないライブラリへのリンクを追加することはできません。 – vikingosegundo

6

、それはあなたが処理するために必要なエッジケースの多くを作成して行います。それから、
は例のコードをです。以下のような:

  • オブジェクトAはsetDelegateを呼び出す場合:, setDelegateを呼び出して、オブジェクトBの直後に:その後、Aは、デリゲートの呼び出しを受けることはありませんオブジェクト。

  • シングルトンのデリゲートを解除する前に、デリゲートであるかどうかを確認する必要があります。通常deallocにはsingleton.delegate = nil;と呼んでいます。あなたがした後に別のオブジェクトが代理人になった場合、あなたはそれらが予期せず代行をやめさせただけです。

デリゲートを持つシングルトンは、定評のあるパターンではありません。ユースケースがどれほど堅牢であるかによって、ソリューションが異なるはずです。ここにいくつかの解決策があります(最も簡単な順に - >最も堅牢です)。

それをシンプルに保つ(これは不可能かもしれない)、同時に複数のオブジェクトはシングルトンのデリゲートされていないようにアプリケーションを設計します。代わりに、代表団のイベントを通知する

NSNotification

使用NSNotificationCenter。このスレッドに投稿されている他の回答をご覧ください。

複数の代表者

複数のデリゲートをサポートするために、あなたのシングルトンを拡張します。 setDelegate:置き換え:addDelegate:removeDelegate:

@property (atomic) NSMutableArray *delegates; 

- (void)addDelegate:(NSObject * <YourProtocol>)foo { 
    [self.delegates addObject:foo]; 
} 
- (void)removeDelegate:(NSObject * <YourProtocol>)foo { 
    [self.delegates removeObject:foo]; 
} 
- (void)signalDelegateEvent { 
    [self.delegates enumerateObjectsUsingBlock:^(id<YourProtocol> obj, 
               NSUInteger idx, 
               BOOL *stop) { 
     // call delegate method `foo` on each delegate 
     if ([obj respondsToSelector:@selector(foo)]) { 
      [obj foo]; 
     } 
    }]; 
} 

私は、多くのアプリケーションで正常にマルチデリゲートパターンを使用していました。このアプローチを選択した場合、マルチスレッドがどのように影響するかを考えてください。

+0

アイデアのおかげで、私は複数のデリゲートソリューションを使用することは考えていませんでした。デリゲートパターンのバリエーションを念頭においてください。 – Chris

+0

デリゲートオブジェクトに置き換えようとしていることを通知するために必要なコールバックを持つのはどうですか? – psobko

+1

このソリューションは、NSArrayの代わりにNSSetを使用して、何も複数のメッセージを受け取らないようにデリゲートを収集することができます。 –