小編致力于用精簡的語言說明不精簡的問題
入門級:
- 1.用ARC管理內(nèi)存
- 2.使用重用機制
- 3.視圖不透明
- 4.避免龐大的XIB
- 5.開啟新線程
- 6.調(diào)整圖片大小
- 7.選擇正確的集合
- 8.打開gzip壓縮
中級:在一些相對復(fù)雜情況下可能用到的
- 9.延遲加載
- 10.緩存
- 11.權(quán)衡渲染方法
- 12.處理內(nèi)存警告
- 13.避免重用大開銷對象:NSDateFormatter申钩、NSCalendar
- 15.避免處理數(shù)據(jù)格式
- 16.選擇正確的數(shù)據(jù)形式
- 18.減少使用Web
- 19.shadowPath替代shadowOffset
- 20.優(yōu)化TableView
- 21.選擇正確的數(shù)據(jù)存儲方法
進階級:這些建議,在你確信他們可以解決問題并且得心應(yīng)手的情況下储矩,采用
- 22.加速啟動時間
- 23.使用Autorelease Pool
- 24.選擇加載圖片方法
- 25.盡量避免日期格式轉(zhuǎn)換
入門級具體講解
1.用ARC管理內(nèi)存
- 自動引用計數(shù)和iOS5一起發(fā)布遵湖,它可以盡量避免內(nèi)存泄露,自動為你管理retain和release的過程
2.在正確的地方使用重用機制
一個開發(fā)中常見的錯誤就是沒有給
UITableViewCells
搀别,UICollectionViewCells
,甚至是UITableViewHeaderFooterViews
設(shè)置正確的reuseIdentifier自iOS6起,你也應(yīng)該在header和footer 的 views中使用reuseIdentifiers
3.盡量把views
設(shè)置為完全不透明
如果有透明的Views南蓬,應(yīng)該設(shè)置它們的
opaque
屬性為YES-
Apple的文檔對于
opaque
屬性的描述是:- 設(shè)置為YES, 系統(tǒng)會優(yōu)化渲染過程哑了,提高性能
- 設(shè)置為NO赘方,系統(tǒng)認為視圖透明,會和其它內(nèi)容一起組成這個視圖
- 默認值是YES
在相對比較靜止的畫面中弱左,設(shè)置這個屬性不會有太大影響窄陡。然而當(dāng)這個view嵌在scrollview里邊,或者是一個復(fù)雜動畫的一部分拆火,不設(shè)置這個屬性的話會在很大程度上影響app的性能
為什么Blending會導(dǎo)致性能的損失跳夭?
如果一個圖層是完全不透明的,則系統(tǒng)直接顯示該圖層的顏色即可。而如果圖層是帶透明效果的,則會引入更多的計算,因為需要把下面的圖層也包括進來,進行混合后顏色的計算
4. 避免過于龐大的XIB
- 加載XIB的時候所有內(nèi)容都被放在了內(nèi)存里们镜,包括圖片币叹。如果有一個不會即刻用到的view,就是在浪費內(nèi)存資源模狭。storyboard僅在需要時加載入內(nèi)存
5. 不要阻塞主線程
6. 調(diào)整圖片大小
- 運行中縮放圖片很消耗資源颈抚,最好保證bundle里圖片大小和imageView大小一致;如果從網(wǎng)絡(luò)中獲取圖片資源嚼鹉,那么最好在新的線程中縮放圖片后贩汉,放在imageView上。
7.選擇正確的集合:
- array中锚赤,有序數(shù)組匹舞,用索引查找相對較快,用值來查找相對較慢线脚,插入刪除很慢
- 字典中赐稽,用key查找比較快
- sets,無序數(shù)組酒贬,用value查找很快又憨,插入刪除很快
8. 打開gzip
壓縮
減小文檔的一個方式就是在服務(wù)端和你的app中打開gzip。這對于文字這種能有更高壓縮率的數(shù)據(jù)來說會有更顯著的效用锭吨。好消息是蠢莺,iOS已經(jīng)在NSURLConnection中默認支持
了gzip壓縮,當(dāng)然AFNetworking這些基于它的框架亦然
中級
9. 延遲加載
UITableView和UICollectionView的操作: 不要一次創(chuàng)建所有的子視圖零如,需要時才創(chuàng)建躏将,當(dāng)它們完成了使命锄弱,把他們放進一個可重用的隊列中
10. Cache
- 緩存那些不大可能改變但是需要經(jīng)常讀取的東西
- 比如UITableView的行高。
- NSCache和NSDictionary類似祸憋,不同的是系統(tǒng)回收內(nèi)存的時候它會自動刪除
11. 權(quán)衡渲染方法
在iOS中可以有很多方法做出漂亮的按鈕会宪。你可以用整幅的圖片,可調(diào)大小的圖片蚯窥,uozhe可以用CALayer掸鹅, CoreGraphics甚至OpenGL來畫它們。
簡單來說拦赠,就是用事先渲染好的圖片更快一些巍沙,因為如此一來iOS就免去了創(chuàng)建一個圖片再畫東西上去然后顯示在屏幕上的程序。問題是你需要把所有你需要用到的圖片放到app的bundle里面荷鼠,這樣就增加了體積 – 這就是使用可變大小的圖片更好的地方了: 你可以省去一些不必要的空間句携,也不需要再為不同的元素(比如按鈕)來做不同的圖。
然而允乐,使用圖片也意味著你失去了使用代碼調(diào)整圖片的機動性矮嫉,你需要一遍又一遍不斷地重做他們,這樣就很浪費時間了牍疏,而且你如果要做一個動畫效果蠢笋,雖然每幅圖只是一些細節(jié)的變化你就需要很多的圖片造成bundle大小的不斷增大。
總得來說鳞陨,你需要權(quán)衡一下利弊挺尿,到底是要性能能還是要bundle保持合適的大小。
12. 處理內(nèi)存警告
- 在appdelegate中的applicationDidReceiveMemoryWarning:方法中接收警告
- 在自定義的UIViewController的子類中覆蓋該方法炊邦,注冊并接收 UIApplicationDidReceiveMemoryWarningNotification 的通知;一旦收到這類通知熟史,你就需要釋放任何不必要的內(nèi)存使用
- 一個有圖片緩存的app可以移除不在屏幕上顯示的圖片
13. 避免重用大開銷對象
避免初始化比較慢的對象馁害,比如
NSDateFormatter
和NSCalendar
可以通過添加屬性到類里或者創(chuàng)建靜態(tài)變量來避免重復(fù)創(chuàng)建對象
X14. 使用Sprite Sheets
你是一個游戲開發(fā)者嗎,那么Sprite sheets一定是一個你的最好的朋友了蹂匹。Sprite sheet可以讓渲染速度加快碘菜,甚至比標(biāo)準(zhǔn)的屏幕渲染方法節(jié)省內(nèi)存。
我們有兩個很好的關(guān)于Sprite的教程:
How To Use Animations and Sprite Sheets in Cocos2D
How to Create and Optimize Sprite Sheets in Cocos2D with Texture Packer and Pixel Formats
第二個教程涵蓋了可能在很大程度上影響你游戲性能的pixel格式的細節(jié)限寞。
如果你對于spirte sheet還不是很熟悉忍啸,可以看下這兩個(youtube)視頻SpriteSheets – The Movie, Part 1 和Part 2。視頻的作者是創(chuàng)建Sprite sheet很流行的工具之一Texture Packer的作者Andreas L?w履植。
除了使用Sprite sheets计雌,其它寫在這里的建議當(dāng)然也可以用于游戲開發(fā)中。比如你需要很多的Sprite sheets玫霎,像敵人凿滤,導(dǎo)彈之類的動作類必備元素妈橄,你可以重用這些sprites而不用每次都要重新創(chuàng)建。
15. 避免處理數(shù)據(jù)格式
- 從服務(wù)器加載的json或xml等數(shù)據(jù)時翁脆,服務(wù)器格式最好方便客戶端操作眷蚓,避免客戶端在內(nèi)存中操作數(shù)據(jù)格式
16. 選擇正確的數(shù)據(jù)形式
- 解析JSON會比XML更快一些
- JSON也通常更小
- 使用SAX 來解析XML就像解析本地文件一樣;不需等到整個文檔下載完成才開始解析反番;當(dāng)處理很大數(shù)據(jù)的時候就會極大地
降低內(nèi)存
占用
X17. 正確設(shè)定背景圖片
在View里放背景圖片就像很多其它iOS編程一樣有很多方法:
使用UIColor的 colorWithPatternImage來設(shè)置背景色沙热;
在view中添加一個UIImageView作為一個子View。
如果你使用全畫幅的背景圖罢缸,你就必須使用UIImageView因為UIColor的colorWithPatternImage是用來創(chuàng)建小的重復(fù)的圖片作為背景的篙贸。這種情形下使用UIImageView可以節(jié)約不少的內(nèi)存:
// You could also achieve the same result in Interface BuilderUIImageView*backgroundView = [[UIImageViewalloc] initWithImage:[UIImageimageNamed:@"background"]];[self.viewaddSubview:backgroundView];
如果你用小圖平鋪來創(chuàng)建背景,你就需要用UIColor的colorWithPatternImage來做了祖能,它會更快地渲染也不會花費很多內(nèi)存:
self.view.backgroundColor= [UIColorcolorWithPatternImage:[UIImageimageNamed:@"background"]];
18. 減少使用Web
-
UIWebView用來展示網(wǎng)頁內(nèi)容歉秫,創(chuàng)建動畫效果
- UIWebView并不像驅(qū)動Safari的那么快。這是由于以JIT compilation 為特色的Webkit的Nitro Engine的限制
移除不必要的javascript养铸,避免使用過大的框架雁芙,能只用原生js就更好了
19. shadowPath替代shadowOffset
...view.layer.shadowOffset=CGSizeMake(-1.0f,1.0f);view.layer.shadowRadius=5.0f;view.layer.shadowOpacity=0.6;
CoreAnimation先在后臺得出圖形,加好陰影钞螟,然后渲染兔甘。開銷很大
view.layer.shadowPath = [[UIBezierPath bezierPathWithRect:view.bounds] CGPath];
20. 優(yōu)化TableView
為了保證TableView平滑滾動,確保你采取了以下的措施:
1.緩存行高
2.盡量設(shè)定固定行高
3.異步加載數(shù)據(jù)
4.視圖不透明
5.減少子視圖
6.盡量不使用 `cellForRowAtIndexPath:` 如果用鳞滨,用一次然后緩存結(jié)果
21. 選擇正確的數(shù)據(jù)存儲方式
1.NSUerDefaults
NSUserDefaults只適用于小數(shù)據(jù)洞焙,比如一些簡單的布爾型的設(shè)置選項
2.使用XML, JSON, 或者 Plist
XML需要讀取整個文件到內(nèi)存里去解析
3.使用NSCoding存檔
需要讀取整個文件到內(nèi)存里去解析
4.SQLite,Core Data
存儲大塊數(shù)據(jù)
SQLite更加底層拯啦,但SQLite和Core Data的性能是差不多的澡匪。他們的不同在于具體使用方法。Core Data代表一個對象的graph model褒链,但SQLite就是一個DBMS
22. 加速啟動時間
1.開啟新線程
比如加載遠端或者數(shù)據(jù)庫數(shù)據(jù)唁情、解析數(shù)據(jù)
2.避免過于龐大的XIB
他們是在主線程上加載的
注意,用Xcode debug時watchdog并不運行甫匹,一定要把設(shè)備從Xcode斷開來測試啟動速度
23. 使用AutoreleasePool
NSAutoreleasePool負責(zé)釋放block中的自動釋放對象甸鸟。一般情況下它會自動被UIKit調(diào)用
假如你創(chuàng)建很多臨時對象,你會發(fā)現(xiàn)內(nèi)存一直在減少直到這些對象被release的時候兵迅。這是因為只有當(dāng)UIKit用光了autorelease pool的時候memory才會被釋放
好消息是你可以在你自己的@autoreleasepool里創(chuàng)建臨時的對象來避免這個行為:
// 千萬不要寫多次autorelease
// 一個alloc, new對應(yīng)一個autorelease
//Person *p = [[[[Person alloc] init] autorelease] autorelease];
// 如果寫了autorelease就不要寫release
// 總之記住: 一個alloc/new對應(yīng)一個autorelease或者release
@autoreleasepool {
Person *p = [[[Person alloc] init] autorelease];
}
24. 選擇是否緩存圖片
imageNamed會緩存圖片
imageWithContentsOfFile僅加載圖片
25. 避免日期格式轉(zhuǎn)換
如果用NSDateFormatter來處理很多日期格式抢韭,應(yīng)該小心。重用NSDateFormatter是好的
然而恍箭,如果你需要更多速度刻恭,那么直接用C是一個好的方案。Sam Soffes有一個不錯的帖子(http://soff.es/how-to-drastically-improve-your-app-with-an-afternoon-and-instruments)
日期格式盡量選擇Unix時間戳扯夭》透鳎可以方便地從時間戳轉(zhuǎn)換到NSDate: 這樣會比用C來解析日期字符串還快:
[NSDatedateWithTimeIntervalSince1970:timestamp];