1.iOS中delegate代理对象使用weak
之前不停的使用assign,今天在调试一段的时候,发现使用assgin的时候程序会crash,报错EXC_BAD_ACCESS, 经过一番研讨,发明如果应用 @property (nonatomic, assign, readwrite) id delegate;,用assign声明一个delegate,那么即便代理指向的对象销毁了,delegate中依然会保持之前对象的地址,即代理成为一个野指针,所以导致程序会crash,而用weak修饰,则不会有上诉的问题,当代理指向的对象销毁后,delegate = nil, 所以为了以后出现问题,最好delegate最好用weak修饰。
下面两种方式都是弱引用代理对象,但是第一种在代理对象被释放后不会导致崩溃,而第二种会导致崩溃。
@property (nonatomic, weak) iddelegate;
@property (nonatomic, assign) iddelegate;
weak和assign是一种“非拥有关系”的指针,通过这两种修饰的指针变量,都不会改变被引用对象的引用计数,但是一个对象被释放后,weak声明的会自动将指针指向nil,而assign则不会,在iOS中向nil对象发送消息时,不会导致奔溃,所以assign就会导致野指针的错误unrecognized selector sent to instance。
总结:如果我们修饰代理属性,最好还是用weak修饰吧,比较安全;
2.nonatomic,assign,copy,retain的区别?
(atomic是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所 以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。)
assign: 简单赋值,不更改索引计数
对基础数据类型 (NSInteger)和C数据类型(int, float, double, char, 等)
copy:建立一个索引计数为1的对象,然后释放旧对象
对NSString
retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1
对其他NSObject和其子类
copy与retain的区别:
copy是创建一个新对象,retain是创建一个指针,引用对象计数加1。
eg: 一个NSString 对象,地址为0×1111 ,内容为@”STR”
在MRC环境下使用retain修饰对象类型,使用assign实现基本类型.
Copy 到另外一个NSString 之后,地址为0×2222 ,内容相同,新的对象retain为1 ,旧有对象没有变化
retain 到另外一个NSString 之后,地址相同(建立一个指针,指针拷贝),内容当然相同,这个对象的retain值+1
也就是说,retain 是指针拷贝,copy 是内容拷贝。
3.定时器,在scrollerView滚动的时候,定时器NSTimer会暂停回调,为什么,如何解决?
RunLoop只能运行在一种mode下,如果要换mode,当前的RunLoop对象也会停止下来,重新开启新的RunLoop对象,利用这个机制,ScrollView在滚动过程中NSDefaultRunLoopMode(kCFRunLoopDefaultMode)的mode会切换到UITrackingRunLoopMode来保证ScrollView的流畅滑动:如果只在NSDefaultRunLoopMode模式下处理的事件会影响ScrollView的滑动,如果我们把一个NSTimer对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主运行循环中的时候, ScrollView滚动过程中会因为mode的切换,而导致NSTimer将不再被调度。
解决方案:Timer计时会被scrollView的滑动影响的问题可以通过将timer添加到NSRunLoopCommonModes(kCFRunLoopCommonModes)来解决。代码如下:
//将timer添加到NSDefaultRunLoopMode中
//然后再添加到NSRunLoopCommonModes里
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerTick:)userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];