我有一个非常标准的案例,为了简单起见,假设有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。
答案 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
实例变量,可以解决你的问题。