0

私はかなり標準的なケースを持っています。簡単にするために、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 ではありません。

4

1 に答える 1

1

これは大まかにここで起こることです:

  • インスタンスのMyController割り当てが解除されると、インスタンス変数_myModelが に設定されnil-[MyModel dealloc]が呼び出されます。
  • その時点では、_delegateインスタンス変数はまだnilではありませんが、指しているオブジェクトが割り当て解除の過程にあるため 、デリゲートにアクセスすると戻ります。nil

(詳細な分析については、dealloc で弱いプロパティが nil に設定されていますが、プロパティの ivar が nil ではないを参照してください。)

モデルはこのオブジェクトがいつ割り当て解除されるかを制御できないため、弱いプロパティを観察することは一般的に危険です。

手動参照カウントと同じ動作が必要な場合は、delegateプロパティを のassign代わりにとして宣言できますweak。これは__unsafe_unretained インスタンス変数を意味し、あなたの場合の問題を解決します。

于 2013-06-11T17:17:31.327 に答える