私はかなり標準的なケースを持っています。簡単にするために、MyController とその MyModel があると仮定します。MyModel の抜粋を次に示します。
@interface MyModel
@property (nonatomic, weak) id<ModelObserver> *delegate;
@end
@implementation MyModel
- (id)initWithDelegate:(id<ModelObserver>)delegate
{
self = [super init];
if (self) {
_delegate = delegate;
// Adds observer for model load and changes
[self addObserver:_delegate];
...
}
- (void)dealloc
{
// Remove delegates and progress indicator
[self removeObserver:_delegate];
@end
これは MyController の抜粋です
@interface MyController
@property (nonatomic, strong) MyModel *_myModel;
@end
@implementation MyController
- (void)commonInit
{
_myModel = [[MyModel alloc] initWithDelegate:self];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
[self commonInit];
}
return self;
}
@end
MyModel にはタイプ id のデリゲートがあります (MyController を指します)。MyController には強力な ivar _myModel があります。MyController はモデルを作成し、割り当て時にデリゲートとして自分自身を渡します。MyModel は MyBaseModel を拡張し、デリゲート (MyController) がオブザーバー リストに追加され、リスト モデルの変更に関する通知を受け取ります。問題は、オブザーバー MyController が [self removeObserver:_delegate]; の前に割り当て解除されることです。オブザーバーリストから削除できるため、後でクラッシュすることがあります。
すでにデバッグを行っており、「[self removeObserver:_delegate];」で実行が停止した場合 MyController はまだ存在します (po _delegate はオブジェクトを出力します)。ただし、_delegate は [self removeObserver:_delegate] に足を踏み入れた直後に nil です。つまり、param は内部から nil です。
更新 deallocで「po _delegate」を実行すると、オブジェクトが表示されるため、nilではありません。しかし、コードが [self removeObserver:_delegate] に入るとすぐに、内部では nil になるため、"removeObserver:" に引数として渡されません。ただし、デバッグ時に「removeObserver:」から dealloc に戻ると、_delegate は再び nil ではありません。