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 ; } ... }