iOS 开发 issue:一个assign 和 weak 的 实例分析

iOS 开发, 使用Objective-C, 属性前面用assign 和 weak 修饰。
使用assign修饰对象,会导致野指针。因为assign修饰的对象销毁后,refence 没有置为nil.

我同事写了很多这样的代码,为什么App运行好好的,从来没有Crash?

@interface ZBStoreInfoVC : UIViewController

@property (nonatomic,assign) id<ZBStoreInfoVCDelegate> delegate;

@end

id<Delegate> delegate 一般赋给另外一个UIViewController,
是对象。不是值类型

阅读 5.3k
3 个回答

1.这么写肯定是会不对的,会崩溃。稍微写个小测试,确实会奔溃。

Book *book = [[Book alloc] init];

{    //从作用域出去后store就会释放
    Store *store = [[Store alloc] init];
    book.delegate = store;
}
[book test];
.....
-(void)test{
    
    NSLog(@"book test");
    
    if ([self.delegate respondsToSelector:@selector(testDelegate)]) {
        [self.delegate testDelegate];
    }
}

2.为什么没出现奔溃?可能是delegate很少优先于self释放,可能delegate因为其他原因没释放(单例或者引用循环等)。一般来说被委托者应该在更深的层级,会先释放,比如界面A->B->C,这样情况,肯定是C作为B的委托,C会先于B释放。这个问题你逐个的检查一下为什么没有奔溃。主要看:是否delegate释放了还回去调用self.delegate之类的。

使用weak修饰时, 当属性所指向的对象内存引用计数为0时会自动赋值为nil, 而assign则不会.
所以当assign修饰的delegate指向的对象dealloc(内存释放)后, 再去访问deleagte系统会奔溃

运行程序有可能会崩溃(有时候不崩溃,你可能需要多运行几次),这是因为当 assign 指针所指向的内存被释放(释放并不等于抹除,只是引用计数为0),不会自动赋值 nil ,这样再引用 self.assignPoint 就会导致野指针操作,如果这个操作发生时内存还没有改变内容,依旧可以输出正确的结果,而如果发生时内存内容被改变了,就会crash。

结论:在 ARC 模式下编程时,指针变量一定要用 weak 修饰,只有基本数据类型和结构体需要用 assgin ,例如 delegate ,一定要用 weak 修饰。

http://bihongbo.com/2014/05/2...
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题