天天看點

iOS面試題:簡述性能優化更多:iOS面試題答案合集

在性能優化中一個最具參考價值的屬性是FPS:Frames Per Second,其實就是螢幕重新整理率,蘋果的iphone推薦的重新整理率是60Hz,也就是說GPU每秒鐘重新整理螢幕60次,這每重新整理一次就是一幀frame,FPS也就是每秒鐘重新整理多少幀畫面。靜止不變的頁面FPS值是0,這個值是沒有參考意義的,隻有當頁面在執行動畫或者滑動的時候,FPS值才具有參考價值,FPS值的大小展現了頁面的流暢程度高低,當低于45的時候卡頓會比較明顯。

圖層混合:

每一個layer是一個紋理,所有的紋理都以某種方式堆疊在彼此的頂部。對于螢幕上的每一個像素,GPU需要算出怎麼混合這些紋理來得到像素RGB的值。

當Sa = 0.5時,RGB值為(0.5, 0, 0),可以看出,當兩個不是完全不透明的CALayer覆寫在一起時,GPU大量做這種複合操作,随着這中操作的越多,GPU越忙碌,性能肯定會受到影響。

公式:

R = S + D * ( 1 – Sa )

結果的顔色是源色彩(頂端紋理)+目标顔色(低一層的紋理)*(1-源顔色的透明度)。

當Sa = 1時,R = S,GPU将不會做任何合成,而是簡單從這個層拷貝,不需要考慮它下方的任何東西(因為都被它遮擋住了),這節省了GPU相當大的工作量。

一、入門級

1、用ARC管理記憶體

2、在正确的地方使用 reuseIdentifier

3、盡量把views設定為透明

4、避免過于龐大的XIB

5、不要阻塞主線程

6、在ImageViews中調整圖檔大小。如果要在UIImageView中顯示一個來自bundle的圖檔,你應保證圖檔的大小和UIImageView的大小相同。在運作中縮放圖檔是很耗費資源的,特别是UIImageView嵌套在UIScrollView中的情況下。如果圖檔是從遠端服務加載的你不能控制圖檔大小,比如在下載下傳前調整到合适大小的話,你可以在下載下傳完成後,最好是用background

thread,縮放一次,然後在UIImageView中使用縮放後的圖檔。

7、選擇正确的Collection。

  • Arrays: 有序的一組值。使用index來lookup很快,使用value lookup很慢, 插入/删除很慢。
  • Dictionaries: 存儲鍵值對。 用鍵來查找比較快。
  • Sets: 無序的一組值。用值來查找很快,插入/删除很快。

8、打開gzip壓縮。app可能大量依賴于伺服器資源,問題是我們的目标是移動裝置,是以你就不能指望網絡狀況有多好。減小文檔的一個方式就是在服務端和你的app中打開gzip。這對于文字這種能有更高壓縮率的資料來說會有更顯著的效用。

iOS已經在NSURLConnection中預設支援了gzip壓縮,當然AFNetworking這些基于它的架構亦然。

二、中級

1、重用和延遲加載(lazy load) Views

  • 更多的view意味着更多的渲染,也就是更多的CPU和記憶體消耗,對于那種嵌套了很多view在UIScrollView裡邊的app更是如此。
  • 這裡我們用到的技巧就是模仿UITableView和UICollectionView的操作: 不要一次建立所有的subview,而是當需要時才建立,當它們完成了使命,把他們放進一個可重用的隊列中。這樣的話你就隻需要在滾動發生時建立你的views,避免了不劃算的記憶體配置設定。

2、Cache, Cache, 還是Cache!

  • 一個極好的原則就是,緩存所需要的,也就是那些不大可能改變但是需要經常讀取的東西。
  • 我們能緩存些什麼呢?一些選項是,遠端伺服器的響應,圖檔,甚至計算結果,比如UITableView的行高。
  • NSCache和NSDictionary類似,不同的是系統回收記憶體的時候它會自動删掉它的内容。

3、權衡渲染方法.性能能還是要bundle保持合适的大小。

4、處理記憶體警告.移除對緩存,圖檔object和其他一些可以重建立的objects的strong references.

5、重用大開銷對象

6、一些objects的初始化很慢,比如NSDateFormatter和NSCalendar。然而,你又不可避免地需要使用它們,比如從JSON或者XML中解析資料。想要避免使用這個對象的瓶頸你就需要重用他們,可以通過添加屬性到你的class裡或者建立靜态變量來實作。

7、避免反複處理資料.在伺服器端和用戶端使用相同的資料結構很重要。

8、選擇正确的資料格式.解析JSON會比XML更快一些,JSON也通常更小更便于傳輸。從iOS5起有了官方内建的JSON deserialization 就更加友善使用了。但是XML也有XML的好處,比如使用SAX 來解析XML就像解析本地檔案一樣,你不需像解析json一樣等到整個文檔下載下傳完成才開始解析。當你處理很大的資料的時候就會極大地減低記憶體消耗和增加性能。

9、正确設定背景圖檔

  • 全屏背景圖,在view中添加一個UIImageView作為一個子View
  • 隻是某個小的view的背景圖,你就需要用UIColor的colorWithPatternImage來做了,它會更快地渲染也不會花費很多記憶體:

10、減少使用Web特性。想要更高的性能你就要調整下你的HTML了。第一件要做的事就是盡可能移除不必要的javascript,避免使用過大的架構。能隻用原生js就更好了。盡可能異步加載例如使用者行為統計script這種不影響頁面表達的javascript。注意你使用的圖檔,保證圖檔的符合你使用的大小。

11、Shadow Path 。CoreAnimation不得不先在背景得出你的圖形并加好陰影然後才渲染,這開銷是很大的。使用shadowPath的話就避免了這個問題。使用shadow path的話iOS就不必每次都計算如何渲染,它使用一個預先計算好的路徑。但問題是自己計算path的話可能在某些View中比較困難,且每當view的frame變化的時候你都需要去update shadow path.

12、優化Table View

  • 正确使用reuseIdentifier來重用cells
  • 盡量使所有的view opaque,包括cell自身
  • 避免漸變,圖檔縮放,背景選人
  • 緩存行高
  • 如果cell内現實的内容來自web,使用異步加載,緩存請求結果
  • 使用shadowPath來畫陰影
  • 減少subviews的數量
  • 盡量不适用cellForRowAtIndexPath:,如果你需要用到它,隻用-一次然後緩存結果
  • 使用正确的資料結構來存儲資料
  • 使用rowHeight, sectionFooterHeight 和 sectionHeaderHeight來設定固定的高,不要請求delegate

13、選擇正确的資料存儲選項

  • NSUserDefaults的問題是什麼?雖然它很nice也很便捷,但是它隻适用于小資料,比如一些簡單的布爾型的設定選項,再大點你就要考慮其它方式了
  • XML這種結構化檔案呢?總體來說,你需要讀取整個檔案到記憶體裡去解析,這樣是很不經濟的。使用SAX又是一個很麻煩的事情。
  • NSCoding?不幸的是,它也需要讀寫檔案,是以也有以上問題。
  • 在這種應用場景下,使用SQLite 或者 Core Data比較好。使用這些技術你用特定的查詢語句就能隻加載你需要的對象。
  • 在性能層面來講,SQLite和Core Data是很相似的。他們的不同在于具體使用方法。
  • Core Data代表一個對象的graph model,但SQLite就是一個DBMS。
  • Apple在一般情況下建議使用Core Data,但是如果你有理由不使用它,那麼就去使用更加底層的SQLite吧。
  • 如果你使用SQLite,你可以用FMDB這個庫來簡化SQLite的操作,這樣你就不用花很多經曆了解SQLite的C API了。

三、進階

1、加速啟動時間。快速打開app是很重要的,特别是使用者第一次打開它時,對app來講,第一印象太太太重要了。你能做的就是使它盡可能做更多的異步任務,比如加載遠端或者資料庫資料,解析資料。避免過于龐大的XIB,因為他們是在主線程上加載的。是以盡量使用沒有這個問題的Storyboards吧!一定要把裝置從Xcode斷開來測試啟動速度

2、使用Autorelease Pool。NSAutoreleasePool`負責釋放block中的autoreleased objects。一般情況下它會自動被UIKit調用。但是有些狀況下你也需要手動去建立它。假如你建立很多臨時對象,你會發現記憶體一直在減少直到這些對象被release的時候。這是因為隻有當UIKit用光了autorelease pool的時候memory才會被釋放。消息是你可以在你自己的@autoreleasepool裡建立臨時的對象來避免這個行為。

3、選擇是否緩存圖檔。常見的從bundle中加載圖檔的方式有兩種,一個是用imageNamed,二是用imageWithContentsOfFile,第一種比較常見一點。

4、避免日期格式轉換。如果你要用NSDateFormatter來處理很多日期格式,應該小心以待。就像先前提到的,任何時候重用NSDateFormatters都是一個好的實踐。如果你可以控制你所處理的日期格式,盡量選擇Unix時間戳。你可以友善地從時間戳轉換到NSDate:

- (NSDate*)dateFromUnixTimestamp:(NSTimeInterval)timestamp {
    return[NSDate dateWithTimeIntervalSince1970:timestamp];
    }

           

這樣會比用C來解析日期字元串還快!需要注意的是,許多web API會以微秒的形式傳回時間戳,因為這種格式在javascript中更友善使用。記住用dateFromUnixTimestamp之前除以1000就好了。

平時你是如何對代碼進行性能優化的?

  • 利用性能分析工具檢測,包括靜态 Analyze 工具,以及運作時 Profile 工具,通過Xcode工具欄中Product->Profile可以啟動,
  • 比如測試程式啟動運作時間,當點選Time Profiler應用程式開始運作後.就能擷取到整個應用程式運作消耗時間分布和百分比.為了保證資料分析在統一使用場景真實需要注意一定要使用真機,因為此時模拟器是運作在Mac上,而Mac上的CPU往往比iOS裝置要快。
  • 為了防止一個應用占用過多的系統資源,開發iOS的蘋果工程師門設計了一個“看門狗”的機制。在不同的場景下,“看門狗”會監測應用的性能。如果超出了該場景所規定的運作時間,“看門狗”就會強制終結這個應用的程序。開發者們在crashlog裡面,會看到諸如0x8badf00d這樣的錯誤代碼。

優化Table View

  • 正确使用reuseIdentifier來重用cells
  • 盡量使所有的view opaque,包括cell自身
  • 如果cell内現實的内容來自web,使用異步加載,緩存請求結果

    減少subviews的數量

  • 盡量不适用cellForRowAtIndexPath:,如果你需要用到它,隻用一次然後緩存結果
  • 使用rowHeight, sectionFooterHeight和sectionHeaderHeight來設定固定的高,不要請求delegate

UIImage加載圖檔性能問題

  • imagedNamed初始化
  • imageWithContentsOfFile初始化
  • imageNamed預設加載圖檔成功後會記憶體中緩存圖檔,這個方法用一個指定的名字在系統緩存中查找并傳回一個圖檔對象.如果緩存中沒有找到相應的圖檔對象,則從指定地方加載圖檔然後緩存對象,并傳回這個圖檔對象.
  • imageWithContentsOfFile則僅隻加載圖檔,不緩存.
  • 加載一張大圖并且使用一次,用imageWithContentsOfFile是最好,這樣CPU不需要做緩存節約時間.
  • 使用場景需要程式設計時,應該根據實際應用場景加以區分,UIimage雖小,但使用元素較多問題會有所凸顯.
    • 不要在viewWillAppear 中做費時的操作:viewWillAppear: 在view顯示之前被調用,出于效率考慮,方法中不要處理複雜費時操作;在該方法設定 view 的顯示屬性之類的簡單事情,比如背景色,字型等。否則,會明顯感覺到 view 有卡頓或者延遲。
    • 在正确的地方使用reuseIdentifier:table view用 tableView:cellForRowAtIndexPath:為rows配置設定cells的時候,它的資料應該重用自UITableViewCell。
    • 盡量把views設定為透明:如果你有透明的Views你應該設定它們的opaque屬性為YES。系統用一個最優的方式渲染這些views。這個簡單的屬性在IB或者代碼裡都可以設定。
    • 避免過于龐大的XIB:盡量簡單的為每個Controller配置一個單獨的XIB,盡可能把一個View Controller的view層次結構分散到單獨的XIB中去, 當你加載一個引用了圖檔或者聲音資源的nib時,nib加載代碼會把圖檔和聲音檔案寫進記憶體。
    • 不要阻塞主線程:永遠不要使主線程承擔過多。因為UIKit在主線程上做所有工作,渲染,管理觸摸反應,回應輸入等都需要在它上面完成,大部分阻礙主程序的情形是你的app在做一些牽涉到讀寫外部資源的I/O操作,比如存儲或者網絡。

      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

      // 選擇一個子線程來執行耗時操作

      dispatch_async(dispatch_get_main_queue(), ^{

      // 傳回主線程更新UI

      });

      });

    • 在Image Views中調整圖檔大小

      如果要在UIImageView中顯示一個來自bundle的圖檔,你應保證圖檔的大小和UIImageView的大小相同。在運作中縮放圖檔是很耗費資源的.

講講你用Instrument優化動畫性能的經曆吧(别問我什麼是Instrument)

Apple的instrument為開發者提供了各種template去優化app性能和定位問題。很多公司都在趕feature,并沒有充足的時間來做優化,導緻不少開發者對instrument不怎麼熟悉。但這裡面其實涵蓋了非常完整的計算機基礎理論知識體系,memory,disk,network,thread,cpu,gpu等等,順藤摸瓜去學習,是一筆巨大的知識财富。動畫性能隻是其中一個template,重點還是了解上面問題當中CPU GPU如何配合工作的知識。

           

facebook啟動時間優化

1.瘦身請求依賴

2.UDP啟動請求先行緩存

3.隊列串行化處理啟動響應

更多:iOS面試題答案合集