1. NSTimer中的target对self进行强引用,导致代码有保留环。
如下代码
__weak typeof(self) weakSelf = self; scheduledTimerWithTimeInterval:0.1 target:weakSelf selector:@selector(update) userInfo:nil repeats:YES];
其中,对self的引用是强引用,如果不注定调用[_timer invalidate]的话,会导致保留环。更糟糕的是,timer还会一直在后台运行。在《Effective Object-C 2.0》第52个topic讨论过这个问题。个人觉得这是NSTimer接口设计的不好,起码应该提供一个weak版本的类似接口给开发者使用。否则,依靠外部每次stop,很容易导致内存泄露的问题。
2.使用原生View进行拼接,比custom view加drawRect性能要更高。
原生的View如UIImageView,UILabel等做了性能优化,它们不通过drawRect实现自身的绘制。而是使用更高效的方式。在苹果的文档中,多次提到:使用view拼凑的方式,比使用drawRect的方法效率更高。而是用drawRect的方式需要注意不要大量消耗CPU性能,否则有可能导致手机耗电和流畅性。
个人在win32上开发时,对于custom draw使用的还是比较频繁的,并没有任何文档指出该方式会导致性能问题。本人觉得导致ios这个差异的关键点在于:iOS使用空间换时间的方式,对所有的view绘制结果进行了缓存。每个view会对应一个layer,view的绘制首先绘制到layer上。再由compositor进行混合渲染。因此,system view会有优化的空间,如果使用drawRect基本上layer缓存的优化会大打折扣。所以,在ios开发中,会建议使用view平凑的方式得到想要的效果。
参考文档:
View and Window Architecture
3.对weakSelf进行强引用,得到的是strongSelf
如,下面的代码
__weak typeof(self) weakSelf = self; __strong typeof(self) strongSelf = weakSelf;
虽然strongSelf引用了一个若引用的self,但是得到的仍然是strongSelf。强弱属性是变量自身的属性,不会在赋值时传递。变量的属性都在声明和定义的时候就定好了。
4.当拖动scrollView时,timer计时器会停止计时,导致计时器相关的UI停止更新的问题。
把计时器用NSRunLoopCommonModes加入到主线程就可以了。
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
5.在block中使用局部self强引用strongSelf来防止weakSelf在代码中间被释放。
__weak __typeof__(self) weakSelf = self; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ __strong __typeof(self) strongSelf = weakSelf; if (strongSelf == nil) return ; [strongSelf doStuff0]; [strongSelf doStuff1]; [strongSelf doStuff2]; });
使用strongSelf,保证在block中self不会被释放,如果使用的是weakSelf,在doStuff0 1 2中的某两个方法之间时,weakSelf可能为空(在调用doStuffx的过程中时,weakSelf不会为空)。如果有类似的多次访问strongSelf又不想每次都坐safeguard的话,可以考虑局部强引用的方式。
6. ARC中的内存问题,release sent to deallocated object问题。
简单来说,在某个dealloc方法中触发了成员变量进行autorelease,但是dealloc过后,该成员变量已经被释放了。这时autorelease再进行release就有可能触发上述crash。如果发生类似事情可以查一下是不是上述原因导致的。参考:release sent to deallocated instance under ARC .. how?
7. 当使用NSTimer驱动View进行更新时,可以在回调中判断view是否可见进行优化。
-(void)timerDidFire { if (self.window == nil) { return ; } ... }