1. NSTimer中的target对self进行强引用,致使代码有保留环。html
以下代码ios
__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性能,不然有可能致使手机耗电和流畅性。app
我的在win32上开发时,对于custom draw使用的仍是比较频繁的,并无任何文档指出该方式会致使性能问题。本人以为致使ios这个差别的关键点在于:iOS使用空间换时间的方式,对全部的view绘制结果进行了缓存。每一个view会对应一个layer,view的绘制首先绘制到layer上。再由compositor进行混合渲染。所以,system view会有优化的空间,若是使用drawRect基本上layer缓存的优化会大打折扣。因此,在ios开发中,会建议使用view平凑的方式获得想要的效果。async
参考文档:
oop
View and Window Architecture
性能
3.对weakSelf进行强引用,获得的是strongSelf优化
如,下面的代码ui
__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 ; } ... }