ARC:Dealloc在我从观察者列表中删除它之前释放委托

时间:2013-06-11 13:57:57

标签: iphone objective-c automatic-ref-counting

我有一个非常标准的案例,为了简单起见,假设有MyController及其MyModel。 Heres是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创建模型并将自己作为委托传递给alloc。 MyModel扩展了MyBaseModel,并将一个委托(MyController)添加到观察者列表中,并获得有关列表模型更改的通知。问题是,观察者MyController在[self removeObserver:_delegate]之前被解除分配;能够从观察者列表中删除它,所以我有时候会崩溃。

已经进行了调试,当执行停止时“[self removeObserver:_delegate];” MyController仍然存在(po _delegate打印出对象)。但是,_delegate在进入[self removeObserver:_delegate]之后就没有了,我的意思是param在内部是零。

更新 如果我在dealloc中执行“po _delegate”,我可以看到对象,所以它不是零。但是一旦代码进入[self removeObserver:_delegate],它就是内部的nil,所以它不会作为参数传递给“removeObserver:”。但是,当我在调试时从“removeObserver:”返回dealloc时,_delegate不再是nil。

1 个答案:

答案 0 :(得分:1)

这大致是这里发生的事情:

  • MyController实例被释放时,其实例变量_myModel为 设置为nil,这会导致-[MyModel dealloc]被调用。
  • 此时,_delegate实例变量尚未nil,但正在访问 委托返回nil因为指向的对象正处于存在的过程中 解除分配。

(有关更详细的分析,请参阅Weak property is set to nil in dealloc but property's ivar is not nil。)

观察弱属性通常是危险的,因为模型无法控制 取消分配此对象时。

如果您只想拥有与手动引用计数相同的行为,则可以声明 delegate属性为assign,而不是weak。这意味着__unsafe_unretained 实例变量,可以解决你的问题。