デリゲートは単純な変数であるため、デリゲートに割り当てると、値が追加されるのではなく上書きされます。配列に変換することもできますが、NSArrayはその中のオブジェクトへの強力な参照を保持するため、潜在的な循環参照を処理する必要があります。(この場合の循環参照は、2つのオブジェクトがお互いを所有していることです。どちらも誰かが所有しているため、どちらも解放されません。お互いを所有しているだけですが、ウィキペディアにはもっとあります。しかし、Objective-Cの典型的なパターンはこの理由ですべての代表者を弱体化させるため。)
NSNotificationCenter
代理人の代わりに、通知の使用を検討することをお勧めします。
1:1ではなく、1:anyです(特別な考慮なしに0を含む)。アイデアは、1つのオブジェクトが通知を投稿し、それに関心のあるオブジェクトがそれを監視するというものです。各オブジェクトは、関心のあるイベントを選択できます。
実行する必要のあるいくつかの手順があります。
- 作成したすべてのデリゲートコードを削除します。
- 通知名に同意します。
- 通知に応答するオブジェクトを登録します。(ここでデリゲートを設定します。)
- 通知を処理します。
- 通知を投稿します(以前に代理人に電話した場所)。
- オブジェクトが破棄されたら、オブジェクトの登録を解除します。
あなたがすることは、おそらく一定の鍵について合意することです。
Keys.h:
extern NSString *MethodOneNotification;
Keys.m:
NSString *MethodOneNotification = @"MethodOneNotification";
次に、登録してfirstViewController
、secondViewController
次のような場所でこのようにしviewDidLoad
ます。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(methodOneNotification:) object:nil];
firstViewController
とsecondViewController
セレクターの両方にハンドラーを提供します。
- (void)methodOneNotification:(NSNotification *)notification {
NSLog(@"%@ got the notification!", [self class]);
}
以前に代理人に電話した場所で通知を呼び出します。
[[NSNotificationCenter defaultCenter] postNotificationName:MethodOneNotification
object:nil];
そして、との両方firstViewController
でsecondViewController
、通知登録を削除する必要があります(確かにdeallocで):
- (void)dealloc {
[[NSNotification defaultCenter] removeObserver:self name:MethodOneNotification
object:nil];
// [super dealloc] if you're not using ARC, but you should be
}
通知ハンドラー内で、通知の送信者にとしてアクセスできますnotification.object
。通知とともに情報を渡す必要がある場合は、postNotification:
を受け入れる別のバリアントを使用できます。NSDictionary
その後、として辞書にアクセスできますnotification.userInfo
。
メッセージを投稿したオブジェクトに値を返す必要がある場合は、投稿者(としてアクセスできるnotification.object
)にメッセージを送信して値を返送する必要があります。例えば:
- (void)methodOneNotification:(NSNotification *)notification {
AppDelegate *appDelegate = notification.object;
[appDelegate returningValue:1];
}
ここで、明らかに、AppDelegateはを定義して処理する必要があります-(void)returningValue:(int)value
。
クラスインスタンスの戻り値を保持する必要があります。もちろん、複数の返品が可能な場合は、それらをreturningValue:
配列で収集する必要があります。しかし、少なくとも循環参照はスキップしました。
これを解決するもう1つの方法は、ブロックを使用することです。ただし、これはこの回答の2倍のサイズになります。:)しかし、結論:デリゲートパターンはこの問題の間違ったパターンです。幸いなことに、他のものは簡単に拾うことができます。