WWDC 2018:Cocoa Touch新特性與改進

今年的Session 202 - What's New in Cocoa Touch是這樣的邏輯:objective-c

  • UIKit舊有功能的性能優化
    • 滾動新增數據預獲取功能
    • 下降圖片渲染沒必要要的內存開銷
    • 優化Auto Layout計算的時間複雜度
  • UIKit舊有功能的API調整
    • 框架中舊的全局變量、常量以及函數被嵌套進對象,使得它們看上去更Swift
    • 淘汰舊版本的編解碼API,新增更安全的編解碼API
  • UIKit的新功能
    • Notification的交互、分組、設置
    • Messages的動態貼紙、iPhone X下Home Bar的交互響應
    • 密碼的自動生成和填充
    • Siri Shortcut

UIKit的性能提高


  • UIKit經過「數據預加載」和「CPU算力調整」來作了滾動優化,這兩項優化對於UITableView和UICollectionView甚至你本身定製的UIScrollView都有效。
  • UIKit針對圖片渲染相關API的優化了內存開銷
  • UIKit優化了Auto Layout運算的開銷

「數據預加載」的背後是一個這樣的故事:

咱們舉UITabelView爲例子,一次完整的Cell加載過程是這樣的:算法

  1. 在UITableView的DataSource的- tableView:cellForRowAt:方法中,工程師將Cell實例從緩存隊列中取出,或直接初始化一個新cell
  2. 工程師將數據取出,而後賦值給Cell實例
  3. UIKit會調用layoutSubviews給cell的子view做佈局
  4. UIKit將cell繪製出來並展現

只有一幀以內作完這4件事情,UITableView滾動的時候纔不會卡。數據庫

在以上4步中,第2步開銷大小是取決於不一樣場合不一樣業務邏輯的。由於有的時候你用於展現這個Cell的數據可能已經預先整理過,直接拿來就可用,不會有什麼大的開銷。但有的時候你用於展現這個Cell的數據是來自於數據庫、或者本地文件、或者其它地方的,那麼就會多一個從其餘地方取數據整理數據的過程,那麼就會增長一筆額外開銷,這一筆開銷就頗有可能致使掉幀卡頓。swift

如上圖所示,在以前UIKit的實現中,預先取數據這個行爲自己也是有的,並且也是異步的。但因爲取數據的時機是跟加載Cell的時機是同時開始的,因此CPU又要預先取數據,也要加載、渲染Cell。這就致使了CPU在一幀的時間內同時作兩件事,就有可能致使掉幀。緩存

而此次的優化,就是把預先取數據的行爲放在了Cell渲染完成以後。這樣就能夠在一幀剛開始的時候,將CPU從數據預加載的事務中解放出來,全力去作Cell相關的事情,這樣就可以儘早將Cell渲染完交差。而後CPU再進行數據異步預加載的事情。安全

在這一輪優化中,UIKit針對數據預加載提供了新的Protocol。拿UITableView來講,就提供了UITableViewDataSourcePrefetching,這個Protocol中包含兩個方法:性能優化

func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath])
func tableView(_ tableView: UITableView, cancelPrefetchingForRowsAt: indexPaths [IndexPath])
複製代碼
- (void)tableView:prefetchRowsAt:
- (void)tableview:cancelPrefetchingForRowsAt:
複製代碼

實現這個protocol時,只有prefetchRowsAt這個方法是必須的。cancelPrefetchingForRowsAt這個會由系統調用,好比當你cell的數據是須要下載才能獲得的,那麼結合斷點續傳功能和這個protocol,你就能很優雅地處理cell數據加載的事情。markdown


「算力調整」的背後是這樣的故事:

蘋果工程師在不斷地作性能檢測的時候,又發現了一個這樣的狀況:若是用戶以前在看一些加載開銷比較小的Cell,而後用戶忽然滾動到加載開銷比較大的Cell時,UIKit依舊會出現掉幀的卡頓現象。並且此時系統自己也沒什麼負載,也沒有什麼開銷大的後臺任務在運行,所以就排除了CPU負載過大致使卡頓這一可能。app

那爲何CPU沒什麼負載,卻依舊出現了卡頓呢?他們研究了一輪,發現原來這是由於CPU性能調度邏輯致使的,這段過程是這樣:框架

  1. 當用戶以前一直在看加載開銷小的Cell的時候,其自己須要的CPU性能並不高,那麼此時CPU性能調度管理器就更加傾向於保持低性能運行,這樣可以省電。
  2. 當用戶忽然劃到一個加載開銷大的Cell的時候,CPU性能調度管理器也並不知道你這時候要加載一個開銷那麼大的Cell,因而它就仍是在低性能的狀態下去加載這個開銷比較大的Cell。
  3. 當CPU性能調度器反應過來這個Cell原來須要那麼大的開銷的時候,它就會切到高性能去消化這個負載。不過每每這時候再提升CPU性能就已經晚了,就有很大概率會致使卡頓。

這個過程每每會發生在Feed流相似的應用中。好比你以前一直在看的Cell都是文字內容的,開銷極小。忽然你劃到視頻Cell了,這個cell開銷很大,CPU性能調度管理器在Cell加載到一半了纔去提升性能等級,那就很容易出現卡頓的狀況了。

找到緣由以後,優化的事情就好作了。如今蘋果工程師打通了整個流程,使得UIKit的信息可以傳遞到CPU性能調度管理器。當UIKit在加載下一個Cell的時候,若是發現這是一個加載開銷比較大的Cell,UIKit就會去通知CPU性能調度器,告訴調度器趕忙提升性能。這樣一來,由於CPU性能已經提早提上來了,那麼系統就能最大可能避免掉幀卡頓的狀況發生。

也就是說,以前CPU的調度狀況是這樣:

優化以後,CPU的調度就變成了這樣:

由於UIKit預測到了下一個Cell開銷比較大,因此提早跟CPU性能調度器打了招呼,因而CPU的性能就馬上提上來了。相比以前CPU性能慢慢往上提的狀況,就更不容易出現卡頓。


圖片渲染相關API的內存優化

演講者先說了一遍內存是如何影響UI性能的,這一段其實能夠說得很簡單:當系統剩餘內存很少,而此時你的應用又須要很大的一片內存時,系統就要經過回收內存或強行關閉後臺App的方式來爲你的應用騰出內存來。系統爲你騰內存這一操做的開銷致使了你的App此時須要更長時間的等待,進而影響了你App的UI性能。

爲了緩解這個問題,iOS 12引入了Automatic Backing Store這項技術。這項技術主要是針對畫圖類的App起做用,對於其餘的場合無效。本質上的實現就是經過在保證色彩不失真的基礎上,使用更少的數據量,去表達一個像素的顏色。

以下圖所示,在64位色的狀況下,左右兩張圖片的數據量是同樣的,都是2.2M左右。雖然右邊只有黑白兩色,可是依舊使用了64位去存儲每一個像素的顏色色值。

因此呢,蘋果就想了個辦法,說既然右邊這張圖片只有黑白兩色,那我幹嗎還要用64位去表達一個顏色呢?8位就足夠了啊。因而,右邊這個圖每像素的顏色用8位來表達以後,就變成只有275K了,因而內存就省了:

那爲何不直接用1位呢?反正也就黑白兩色。對不起,由於色表標準最小就是8位的,若是你用了1位色,屏幕是不支持這套標準的。Automatic Backing Store對左邊這幅圖無效,由於它不是圖片壓縮算法,它只是在你用畫筆畫完圖片而且渲染的時候,把原來須要64位去存儲的單個像素的色值,改爲用8位去存儲而已,這個過程是有可能產生必定的色彩失真的。因此Automatic Backing Store只適合畫圖類應用,在如下3個場景中,它是默認開啓的:

  • UIView.draw()
  • UIGraphicsImageRenderer
  • UIGraphicsImageRenderer.Range

有關Automatic Backing Store的內容,還能夠看Session 219 - Image and Graphics Best Practices


Auto Layout計算的優化

iOS 12中,Auto Layout作了很是大的優化。

當一個View包含了N個佈局上互相獨立的子View時,Auto Layout的計算耗時是隨着子view數量的增長而線性增長的。由於蘋果工程師們的努力,iOS 12的計算耗時比iOS 11少了一些,以下圖:

圖A

當一個View包含了N個子View,且這N個子View的佈局存在依賴的狀況時。iOS 11下Auto Layout的計算耗時是隨着子View的數量增長而指數性增加的。在iOS 12優化以後,計算耗時呈線性增加,這能夠說是一個比較大的優化了。(但我一直是認爲其實這自己就應該是一個線性時間內能夠完成的任務,iOS 11的時候工程師怎麼把它實現成指數性增加的了?這個工程師該殺),以下圖:

當N個View相互嵌套時,iOS 11下Auto Layout的計算耗時是隨着子View的數量增長而指數性增加的。在iOS 12優化以後,計算耗時呈線性增加。我仍是以爲這自己也是一個線性時間內能夠完成的任務,當初在iOS 11把它實現成指數性增加任務的工程師該殺。以下圖:

更多的內容能夠看Session 220 - High Performance Auto Layout


UIKit舊有API的修改


  • 更Swift的UIKit
  • 更安全的編解碼

更Swift的UIKit

在Swift 4.2中,有些全局的Type被挪進了對象中,包括但不限於:

還有些全局常量也被挪進了有關對象中,包括但不限於:

還有些全局函數也被挪近了有關對象中,包括但不限於:

這麼一來,UIKit看起來確實更Swift了,只是升級4.2的時候,又要面對一堆編譯錯誤了。


更安全的編解碼

演講者只是在這裏提了一句,iOS 12提供了更安全的編解碼API,舊的API將會被淘汰。具體是什麼狀況要去看Session 222 - Data You Can Trust


UIKit 新功能


  • Notification
  • Messages
  • Automatic Passwords and Security Code AutoFill
  • Siri Shortcuts

Notification API修改

  • Interaction

    • iOS 12增強了針對Notification的交互,大部分界面開發者能夠自由定製了。
  • Grouping

    • iOS 12會將衆多Notification分組並展現,而且提供了API讓開發者在必定程度上決定如何進行分組。
  • Settings

    • iOS 12向開發者提供了接口,使得開發者可以讓用戶直接開啓或關閉通知。

以上三點演講者只是一帶而過,更多內容請看:

Session 710 - What's New in User Notifications

Session 711 - Using Grouped Notifications


Messages

iOS 12中,你能夠將Message的人臉識別貼紙帶入camera中。若是你須要針對這些作更多的定製的話,你須要在Info.Plist中添加如下內容,MSMessagesAppPresentationContextMedia其實就是指的camera:

<key>MSSupportedPresentationContexts</key>
<array>
    <string>MSMessagesAppPresentationContextMessages</string>
    <string>MSMessagesAppPresentationContextMedia</string>
</array>
複製代碼

並且你也能夠根據如下API查看一條Message是否是動態的:

var presentationContext: MSMessagesAppPresentationContext

enum MSMessagesAppPresentationContext : UInt {
 case messages
 case media
}
複製代碼

iOS 12也給Message添加了新的交互操做:以前在底部bar處水平滑動,系統會自動切換App。如今你的Message App能夠接收這個事件,能夠選擇覆蓋系統切換App的行爲,或者執行你本身的行爲。


Automatic Passwords and Security Code AutoFill

以前的iOS版本中,已經實現了自動輸入密碼的功能:

在iOS 12中,工程師能夠在修改密碼的地方也彈出提示,告知用戶是否須要將密碼保存在iCloud Keychain:

iOS 12還可以幫你自動生成密碼,在註冊流程和修改密碼流程都能用,只要開發者給Password的輸入框打上tag告知這是一個密碼輸入框就行了:

在輸入手機號,發送驗證碼,輸入驗證碼流程中,iOS 12在鍵盤上提供了讀取驗證碼的功能,這樣可以使得用戶沒必要切來切去:

以上這些內容演講者也都只是稍微提了一下,具體內容能夠看這裏:Session 204 - Automatic Strong Passwords and Security Code AutoFill


Safe Area

演講者把以前就已經有的SafeArea Insets講了一遍,沒有提到任何新內容。只是說但願你們可以儘早使用Safe Area Insets去作不一樣設備的UI適配。

最後給到了一個Session:Session 235 - UIKit: Apps for Every Size and Shape,根據演講者的說法來看,這個Session裏面可能有新內容,你們如果有興趣的話能夠看一看。


Siri Shortcuts

Siri Shortcurs可以使得你的App響應Siri的調度。具體的作法是響應來自各個App的Intents。固然,你也能夠給本身的App設定Intents。每個Intents都有不一樣的類型:

Siri會根據Intent找到對應的App,而後再解析用戶給出的指令,來決定本次操做是哪一種類型,進而開發者給到對應的響應操做。

具體的狀況仍是要看如下這些Session:

Session 211 - Introduction to Siri Shortcuts

Session 214 - Building for Voice with Siri Shortcuts

Session 217 - Siri Shortcuts on the Siri Watch Face


以上就是WWDC 2018 - Session 202 - What's New in Cocoa Touch的解說

相關文章
相關標籤/搜索