關於iOS開發中比較常見的優化

weixin_34185560發表於2016-09-11

一. 如何讓你的應用程式更加省電?
答:
(1). 如果程式用到定位,需要在定位完畢之後關閉定位,或者降低定位的頻率,不停的定位會消耗電量。(2). 如果用到了藍芽,需要使用藍芽時候開啟藍芽,藍芽用完之後關閉藍芽,藍芽也很耗電。
(3). 優化演算法,減少迴圈次數,大量迴圈會讓CPU一直處於忙碌狀態,特別費電。
(4). 儘量不要使用網路輪詢(心跳包、定時器),使用推送。
(5). timer的時間間隔不宜太短,滿足需求即可。
(6). 不要頻繁重新整理頁面,能重新整理1行cell的最好重新整理一行,儘量不要reloadData。
(7). 執行緒適量,不宜過多。

二、簡單描述一下你在開發的過程中,如何實現程式的效能優化?

答:我在開發的過程中會注意一下幾點來優化程式效能:

1).避免龐大的XIB、Storyboard,儘量多用純程式碼開發
2).使用懶載入的方式延遲載入介面
3).避免反覆處理資料
4).避免使用NSDateFormatter和NSCalendar。

5).圖片快取的取捨UIImage載入圖片方式一般有兩種:A:imagedNamed初始化B:imageWithContentsOfFile初始化二者不同之處在於,imageNamed預設載入圖片成功後會記憶體中快取圖片,這個方法用一個指定的名字在系統快取中查詢並返回一個圖片物件.如果快取中沒有找到相應的圖片物件,則從指定地方載入圖片然後快取物件,並返回這個圖片物件.而imageWithContentsOfFile則僅只載入圖片,不快取.大量使用imageNamed方式會在不需要快取的地方額外增加開銷CPU的時間來做這件事.當應用程式需要載入一張比較大的圖片並且使用一次性,那麼其實是沒有必要去快取這個圖片的,用imageWithContentsOfFile是最為經濟的方式,這樣不會因為UIImage元素較多情況下,CPU會被逐個分散在不必要快取上浪費過多時間.使用場景需要程式設計時,應該根據實際應用場景加以區分,UIImage雖小,但使用元素較多問題會有所凸顯.

三、tableView的重用機制?(簡單瞭解即可)

檢視UITableView標頭檔案,會找到NSMutableArray* visiableCells,和NSMutableDictnery*reusableTableCells兩個結構。visiableCells內儲存當前顯示的cells,reusableTableCells儲存可重用的cells。TableView顯示之初,reusableTableCells為空,那麼tableViewdequeueReusableCellWithIdentifier:CellIdentifier返回nil。開始的cell都是通過[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]來建立,而且cellForRowAtIndexPath只是呼叫最大顯示cell數的次數。比如:有100條資料,iPhone一屏最多顯示10個cell。程式最開始顯示TableView的情況是:1.用
[[UITableViewCellalloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:CellIdentifier]

建立10次cell,並給cell指定同樣的重用標識(當然,可以為不同顯示型別的cell指定不同的標識)。並且10個cell全部都加入到visiableCells陣列,reusableTableCells為空。2.向下拖動tableView,當cell1完全移出螢幕,並且cell11(它也是alloc出來的,原因同上)完全顯示出來的時候。cell11加入到visiableCells,cell1移出visiableCells,cell1加入到reusableTableCells。3.接著向下拖動tableView,因為reusableTableCells中已經有值,所以,當需要顯示新的cell,cellForRowAtIndexPath再次被呼叫的時候,tableViewdequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。cell1加入到visiableCells,cell1移出reusableTableCells;cell2移出visiableCells,cell2加入到reusableTableCells。之後再需要顯示的Cell就可以正常重用了。

四、如何減小一個應用程式佔用儲存空間?

檢查程式 去掉多餘的xib。iOS App Store相關因素作為提交到App Store中app裡的可執行檔案是被加過密的。加密的副作用是可執行檔案的壓縮效果沒有之前的好了。Build Settings編譯選項,將build setting中的Optimization Level設定為Fastest, Smallest [-Os];將build setting中的Strip Debug Symbols During Copy設定為YES(COPY_PHASE_STRIP = YES),這樣可以減小編譯出二進位制檔案的尺寸。Target針對較少的CPUs對程式指定的特定CPU型別做優化處理,以生成相對於的可執行檔案。不同的硬體,將執行不同的可執行程式碼。雖然這樣優化後的程式,只能針對某些裝置執行,但是這大大減小可執行程式的大小。要想只設定特定型別的CPUs,可以修改build setting中的Architectures,將其從Standard $(ARCHS_STANDARD)修改為你希望支援的列表中對應的特定型別CPU。有效的CPU名稱列在Valid Architectures (VALID_ARCHS) build setting中。請不要修改Valid Architectures設定項,最好由Xcode管理。儘量使用8-bit圖片。使用8-bit的PNG圖片,比32-bit的圖片能減少4倍的壓縮率。由於8-bit的圖片支援最多256種不同的顏色,所以8-bit的圖片一般只應該用於一小部分的顏色圖片。例如灰度圖片最好使用8-bit

五、如何提高一個應用程式的效能?

1、使用ARC減少記憶體失誤,dealloc需要重寫並對屬性置nil。2、重用。3、儘量少使用透明或半透明。會產生額外的運算。4、少用運算獲得圓角,不論view.maskToBounds還是layer.clipToBounds都會有很大資源開銷,必須要用圓角的話不如圖片本身就做成圓角。5、不要阻塞主執行緒。6、使用正確的容器型別。7、圖片與imageView相同大小避免多餘運算。8、使用懶載入。9、使用繪製。

六、如何優化記憶體?

(1).用ARC管理記憶體ARC(Automatic ReferenceCounting,自動引用計數)和iOS5一起釋出,它避免了最常見的也就是經常是由於我們忘記釋放記憶體所造成的記憶體洩露。它自動為你管理retain和release的過程,除了幫你避免記憶體洩露,ARC還可以幫你提高效能,它能保證釋放掉不再需要的物件的記憶體。(2).在正確的地方使用reuseIdentifier一個開發中常見的錯誤就是沒有給UITableViewCells,UICollectionViewCells,甚至是UITableViewHeaderFooterViews設定正確的reuseIdentifier。
(3).儘量把views設定為透明如果你有透明的Views你應該設定它們的opaque屬性為YES。原因是這會使系統用一個最優的方式渲染這些views。如果設為YES,渲染系統就認為這個view是完全不透明的,這使得渲染系統優化一些渲染過程和提高效能。如果設定為NO,渲染系統正常地和其它內容組成這個View。預設值是YES。
(4).避免過於龐大的XIB當你載入一個XIB的時候所有內容都被放在了記憶體裡,包括任何圖片。如果有一個不會即刻用到的view,你這就是在浪費寶貴的記憶體資源了。
(5).不要阻塞主執行緒永遠不要使主執行緒承擔過多。因為UIKit在主執行緒上做所有工作,渲染,管理觸控反應,回應輸入等都需要在它上面完成。一直使用主執行緒的風險就是如果你的程式碼真的block了主執行緒,你的app會失去反應。大部分阻礙主程式的情形是你的app在做一些牽涉到讀寫外部資源的I/O操作,比如儲存或者網路。
(6).在Image Views中調整圖片大小如果要在UIImageView
中顯示一個來自bundle的圖片,你應保證圖片的大小和UIImageView的大小相同。在執行中縮放圖片是很耗費資源的,特別是UIImageView
巢狀在UIScrollView
中的情況下。如果圖片是從遠端服務載入的你不能控制圖片大小,比如在下載前調整到合適大小的話,你可以在下載完成後,最好是用background thread,縮放一次,然後在UIImageView中使用縮放後的圖片。
(7).選擇正確的Collection學會選擇對業務場景最合適的類或者物件是寫出能效高的程式碼的基礎。當處理collections時這句話尤其正確。一些常見collection的總結:·Arrays:有序的一組值。使用index來lookup很快,使用value lookup很慢,插入/刪除很慢。·Dictionaries:儲存鍵值對。用鍵來查詢比較快。·Sets:無序的一組值。用值來查詢很快,插入/刪除很快。
(8).開啟gzip壓縮大量app依賴於遠端資源和第三方API,你可能會開發一個需要從遠端下載XML, JSON, HTML或者其它格式的app。問題是我們的目標是移動裝置,因此你就不能指望網路狀況有多好。一個使用者現在還在edge網路,下一分鐘可能就切換到了3G。不論什麼場景,你肯定不想讓你的使用者等太長時間。減小文件的一個方式就是在服務端和你的app中開啟gzip。這對於文字這種能有更高壓縮率的資料來說會有更顯著的效用。好訊息是,iOS已經在NSURLConnection中預設支援了gzip壓縮,當然AFNetworking這些基於它的框架亦然。像Google App Engine這些雲服務提供者也已經支援了壓縮輸出。
(9).重用和延遲載入(lazy load) Views更多的view意味著更多的渲染,也就是更多的CPU和記憶體消耗,對於那種巢狀了很多view在UIScrollView裡邊的app更是如此。這裡我們用到的技巧就是模仿UITableView
和UICollectionView的操作:不要一次建立所有的subview,而是當需要時才建立,當它們完成了使命,把他們放進一個可重用的佇列中。這樣的話你就只需要在滾動發生時建立你的views,避免了不划算的記憶體分配。建立views的能效問題也適用於你app的其它方面。想象一下一個使用者點選一個按鈕的時候需要呈現一個view的場景。有兩種實現方法:1.建立並隱藏這個view當這個screen載入的時候,當需要時顯示它;2.當需要時才建立並展示。每個方案都有其優缺點。用第一種方案的話因為你需要一開始就建立一個view並保持它直到不再使用,這就會更加消耗記憶體。然而這也會使你的app操作更敏感因為當使用者點選按鈕的時候它只需要改變一下這個view的可見性。第二種方案則相反-消耗更少記憶體,但是會在點選按鈕的時候比第一種稍顯示卡頓。
(10). Cache, Cache,還是Cache!一個極好的原則就是,快取所需要的,也就是那些不大可能改變但是需要經常讀取的東西。我們能快取些什麼呢?一些選項是,遠端伺服器的響應,圖片,甚至計算結果,比如UITableView的行高。NSURLConnection預設會快取資源在記憶體或者儲存中根據它所載入的HTTP Headers。你甚至可以手動建立一個NSURLRequest然後使它只載入快取的值。
(11).權衡渲染方法在iOS中可以有很多方法做出漂亮的按鈕。你可以用整幅的圖片,可調大小的圖片,uozhe可以用CALayer,CoreGraphics甚至OpenGL來畫它們。當然每個不同的解決方法都有不同的複雜程度和相應的效能。簡單來說,就是用事先渲染好的圖片更快一些,因為如此一來iOS就免去了建立一個圖片再畫東西上去然後顯示在螢幕上的程式。問題是你需要把所有你需要用到的圖片放到app的bundle裡面,這樣就增加了體積–這就是使用可變大小的圖片更好的地方了:你可以省去一些不必要的空間,也不需要再為不同的元素(比如按鈕)來做不同的圖。然而,使用圖片也意味著你失去了使用程式碼調整圖片的機動性,你需要一遍又一遍不斷地重做他們,這樣就很浪費時間了,而且你如果要做一個動畫效果,雖然每幅圖只是一些細節的變化你就需要很多的圖片造成bundle大小的不斷增大。總得來說,你需要權衡一下利弊,到底是要效能能還是要bundle保持合適的大小。
(12).處理記憶體警告一旦系統記憶體過低,iOS會通知所有執行中app。如果你的app收到了記憶體警告,它就需要儘可能釋放更多的記憶體。最佳方式是移除對快取,圖片object和其他一些可以重建立的objects的strong references.幸運的是,UIKit提供了幾種收集低記憶體警告的方法:· 在app delegate中使用applicationDidReceiveMemoryWarning:
的方法· 在你的自定義UIViewController的子類(subclass)中覆蓋didReceiveMemoryWarning
· 註冊並接收UIApplicationDidReceiveMemoryWarningNotification的通知一旦收到這類通知,你就需要釋放任何不必要的記憶體使用。例如,UIViewController的預設行為是移除一些不可見的view,它的一些子類則可以補充這個方法,刪掉一些額外的資料結構。一個有圖片快取的app可以移除不在螢幕上顯示的圖片。
(13).重用大開銷物件一些objects的初始化很慢,比如NSDateFormatter和NSCalendar。然而,你又不可避免地需要使用它們,比如從JSON或者XML中解析資料。想要避免使用這個物件的瓶頸你就需要重用他們,可以通過新增屬性到你的class裡或者建立靜態變數來實現。注意如果你要選擇第二種方法,物件會在你的app執行時一直存在於記憶體中,和單例(singleton)很相似。還需要注意的是,其實設定一個NSDateFormatter的速度差不多是和建立新的一樣慢的!所以如果你的app需要經常進行日期格式處理的話,你會從這個方法中得到不小的效能提升。
(14).減少使用Web特性UIWebView很有用,用它來展示網頁內容或者建立UIKit很難做到的動畫效果是很簡單的一件事。但是你可能有注意到UIWebView並不像不像驅動Safari的那麼快。這是由於以JIT compilation為特色的Webkit的Nitro Engine的限制。所以想要更高的效能你就要調整下你的HTML了。第一件要做的事就是儘可能移除不必要的javascript,避免使用過大的框架。能只用原生js就更好了。另外,儘可能非同步載入例如使用者行為統計script這種不影響頁面表達的javascript。最後,永遠要注意你使用的圖片,保證圖片的符合你使用的大小。使用Sprite sheet提高載入速度和節約記憶體。
(15).優化Table ViewTable view需要有很好的滾動效能,不然使用者會在滾動過程中發現動畫的瑕疵。為了保證table view平滑滾動,確保你採取了以下的措施:· 正確使用reuseIdentifier
來重用cells· 儘量使所有的view opaque,包括cell自身· 避免漸變,圖片縮放,後臺選人· 快取行高· 如果cell內現實的內容來自web,使用非同步載入,快取請求結果· 使用shadowPath
來畫陰影· 減少subviews的數量·儘量不適用cellForRowAtIndexPath:
,如果你需要用到它,只用一次然後快取結果· 使用正確的資料結構來儲存資料· 使用rowHeight
,sectionFooterHeight
和sectionHeaderHeight
來設定固定的高,不要請求delegate
(16).使用Autorelease PoolNSAutoreleasePool
負責釋放block中的autoreleased objects。一般情況下它會自動被UIKit呼叫。但是有些狀況下你也需要手動去建立它。假如你建立很多臨時物件,你會發現記憶體一直在減少直到這些物件被release的時候。這是因為只有當UIKit用光了autorelease pool的時候memory才會被釋放。好訊息是你可以在你自己的@autoreleasepool裡建立臨時的物件來避免這個行為:
NSArray *urls = <# An array of file URLs #>;for(NSURL *url in urls) {@autoreleasepool {NSError *error;NSString fileContents = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];/ Process the string, creating and autoreleasing more objects. */}}

這段程式碼在每次遍歷後釋放所有autorelease物件
(17).選擇是否快取圖片常見的從bundle中載入圖片的方式有兩種,一個是用imageNamed
,二是用imageWithContentsOfFile
,第一種比較常見一點。既然有兩種類似的方法來實現相同的目的,那麼他們之間的差別是什麼呢?imageNamed
的優點是當載入時會快取圖片。imageNamed
的文件中這麼說:這個方法用一個指定的名字在系統快取中查詢並返回一個圖片物件如果它存在的話。如果快取中沒有找到相應的圖片,這個方法從指定的文件中載入然後快取並返回這個物件。相反的,imageWithContentsOfFile
僅載入圖片。如果你要載入一個大圖片而且是一次性使用,那麼就沒必要快取這個圖片,用imageWithContentsOfFile
足矣,這樣不會浪費記憶體來快取它。然而,在圖片反覆重用的情況下imageNamed
是一個好得多的選擇。

七、如何加強iOS裡的列表滾動時的順暢感?

1、UITableViewCell裡不要新增太多subview,最好只新增一個cellview。
2、UITableViewCell上的子View的opaque屬性設為YES。其實預設也是不透明。UITableViewCell儘量不要包含透明的子View。
3、在cellview裡,重寫drawRect函式繪製UITableViewCell的內容。
4、在繪製字串時,儘可能使用drawAtPoint: withFont:,而不要使用更復雜的drawAtPoint:(CGPoint)point forWidth:(CGFloat)width withFont:(UIFont *)font lineBreakMode:(UILineBreakMode)lineBreakMode;如果要繪製過長的字串,建議自己先截斷,然後使用drawAtPoint: withFont:方法繪製。
5、在繪製圖片時,儘量使用drawAtPoint,而不要使用drawInRect。drawInRect如果在繪製過程中對圖片進行放縮,會特別消耗CPU。
6、如果繪製cell過程中,需要下載cell中的圖片,建議在繪製cell一段時間後再開啟圖片下載任務。譬如先畫一個預設圖片,然後在0.5S後開始下載本cell的圖片。
7、即使下載cell圖片是在子執行緒中進行,在繪製cell過程中,也不能開啟過多的子執行緒。最好只有一個下載圖片的子執行緒在活動。否則也會影響UITableViewCell的繪製,因而影響了UITableViewCell的滑動速度。(建議結合使用NSOpeartion和NSOperationQueue來下載圖片,如果想盡可能找的下載圖片,可以把[self.queuesetMaxConcurrentOperationCount:4];)
8、最好自己寫一個cache,用來快取UITableView中的UITableViewCell,這樣在整個UITableView的生命週期裡,一個cell只需繪製一次,並且如果發生記憶體不足,也可以有效的釋放掉快取的cell。
9、不要將tableview的背景顏色設定成一個圖片。這回嚴重影響UITableView的滑動速度。在限時免費搜尋裡,我曾經翻過一個錯誤:self.tableView_.backgroundColor = [UIColorcolorWithPatternImage:[UIImageimageNamed:@"background.png"]];通過這種方式設定UITableView的背景顏色會嚴重影響UTIableView的滑動流暢性。修改成self.tableView_.backgroundColor = [UIColor clearColor];之後,fps從43上升到60左右。滑動比較流暢。
10、cell的行高不是固定值,需要計算,則要儘可能快取行高值,避免重複計算行高。這裡指的是UITableViewDelegate裡的行高函式。
八、怎麼解決快取池滿的問題(cell)
ios中不存在快取池滿的情況,因為通常我們ios中開發,物件都是在需要的時候才會建立,有種常用的說話叫做懶載入,還有在UITableView中一般只會建立剛開始出現在螢幕中的cell,之後都是從快取池裡取,不會在建立新物件。快取池裡最多也就一兩個物件,快取池滿的這種情況一般在開發java中比較常見,java中一般把最近最少使用的物件先釋放。
//清楚cell的快取NSArray *subviews = [[NSArray alloc] initWithArray:cell.contentView.subviews];for (UIView *subview in subviews) {[subview removeFromSuperview];

九、TableView是怎麼優化的?tableView下拉載入資料的時候為什麼會出現卡頓,如何解決?

(1)使用不透明檢視
(2)不要重複建立不必要的table cell。
(3)減少檢視的數目。
(4)不要做多餘的繪製工作。
(5)預渲染影像。
(6)不要阻塞主執行緒。

十、正常使用應用時,按HOME鍵退出。稍後再次開啟,介面出現卡頓現象,嘗試分析一下可能原因。

這是由iOS系統管理決定的,但APP退出在後臺後,只有10秒的持續執行時間,然後暫停。但該APP還在記憶體中,當出現記憶體警告,也就是別的APP要執行,而此時記憶體又不足的情況下,系統會回收停在後臺APP所佔用的記憶體。如果出現這種情況,那麼你再次開啟你的APP,就會重新啟動。不知道你是為什麼要讓APP在後臺還要繼續執行,如果非得這樣,那可以使用多執行緒技術中的gcd,可以讓APP退出後繼續執行很長一段時間(大概10分鐘)iOS APP型別:1.儲存現場。按下Home鍵10秒內直接殺死程式,並釋放記憶體。
iOS支援的“多工”。按下Home鍵轉入多工狀態,保留在記憶體中,但只能系統允許的動作:比如GPS,比如VoIP,比如音樂等等。3.真正的桌面級別的多工。只有Safari/Mail是,蘋果嫡系大都都不是。這個級別的app在後臺沒有任何限制動作。無限制動作的程式,一會在使用者無察覺的情況下耗光電力,二會有安全上面的問題(那些在後臺依舊默默傳送你的個人訊息程式)順便提一句,後兩種佔用記憶體的app,也會在任意時間從記憶體中被砍掉,取決於你是否動用了其它app而導致記憶體不足。真正不會被砍掉的後臺,只有蘋果那個通知系統。

.什麼時候會用到懶載入?如果需要展示大量圖片的時候還要一個個去載入麼?

懶載入,又稱為延遲載入。說的通俗一點,就是在開發中,程式啟動的時候不載入資源,只有在執行當需要一些資源時,再去載入這些資源。我們知道iOS裝置的記憶體有限,如果在程式在啟動後就一次性載入將來會用到的所有資源,那麼就有可能會耗盡iOS裝置的記憶體。這些資源例如大量資料,圖片,音訊等等

工程中的圖片存在哪裡,如何保證重新整理後記憶體不斷增加問題,以及節約使用者流量?

工程中使用的圖片可以自己建立個資料夾進行存放你需要用的圖片,也可以在你工程中的Images.xcassets檔案中存放你的圖片.解決重新整理記憶體不斷增加的問題,需要把你建立的控制元件佈局寫成對應類的屬性,在ViewDidLoad中初始化一次.不要在其他的類方法裡建立控制元件.重新整理節約使用者流量的方法就是在一定時間段中判斷當前的請求時間和上次重新整理的時間並限定一個時間範圍在某個範圍內重新整理不重新請求資料.

相關文章