[ WWDC2018 ] - Web安全策略 Strategies for Securing

UICollectionView性能對比,item自動適配大小,iOS 11看上去有掉幀卡頓的現象,iOS 12表現完美,沒有掉幀。ios

WX20180612-104339.png緩存

 

下面是iOS 11和iOS 12的性能對比,灰色條是iOS 11的耗時,藍色條是iOS 12的耗時。在iOS 12上會很大程度改善你的應用程序。less

WX20180619-160559.pngide

實現和感觀

render loop

render loop 是一個每秒鐘跑120次的一個進程,是爲了確保全部的內容都能爲每個frame作好準備。lender loop 一共包括三個步驟來更新約束,佈局和渲染。工具

  • 首先,每個須要接收到更新約束的view會從子view向上傳遞,直到window
  • 而後,每個接收到的view開始layoutsubviews,和更新約束是從相反的方向開始,layout從window開始到每個子view進行layout。
  • 最後,每個須要渲染的view,和layout相同,從父view向子view開始渲染。

在這裏我仍是要推薦下我本身建的iOS開發學習羣:680565220,羣裏都是學ios開發的,若是你正在學習ios ,小編歡迎你加入,今天分享的這個案例已經上傳到羣文件,你們都是軟件開發黨,不按期分享乾貨(只有iOS軟件開發相關的),包括我本身整理的一份2018最新的iOS進階資料和高級開發教程oop

WX20180619-160634.png佈局

render loop目的是爲了不重複的工做。
舉一個例子:一個UILable 須要一個約束來描述它的大小,可是有不少屬性會影響他的大小,設置它的font,text size等等都會受到影響。當一個屬性改變的時候,可能text其餘屬性也會被從新賦值
,頗有可能調用一堆屬性的setter方法,這樣效率會很低。
只須要調用updateConstraints 並指定好要更新的屬性,render loop會幫助你計算好它的frame並完成渲染,從而避免屢次設置的重複工做。性能

 

WX20180619-160709.png學習

在設置約束的一些很差的寫法,每次開始的時候調用deactivate,設置結束以後調用activate。至關於layoutsubviews,每次調用layoutsubviews你銷燬你subviews,從新建立在從新添加。這樣性能不會很好。ui

// Don’t do this! Removes and re-adds constraints potentially at 120 frames per second
    override func updateConstraints() {
        NSLayoutConstraint.deactivate(myConstraints)
        myConstraints.removeAll()
        let views = ["text1":text1, "text2":text2]
        myConstraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|-[text1]-[text2]",
                                                        options: [.alignAllFirstBaseline],
                                                        myConstraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|-[text1]-|",
                                                                                                        metrics: nil, views: views)
            options: [],
            metrics: nil, views: views)
        NSLayoutConstraint.activate(myConstraints)
        super.updateConstraints()
    }

每次都是移除並從新添加,至關於這樣的代碼

// Don’t do this! Removes and re-adds constraints potentially at 120 frames per second
    override func layoutSubviews() {
        text1.removeFromSuperview()
        text1 = nil
        text1 = UILabel(frame: CGRect(x: 20, y: 20, width: 300, height: 30))
        self.addSubview(text1)
        
        text2.removeFromSuperview()
        text2 = nil
        text2 = UILabel(frame: CGRect(x: 340, y: 20, width: 300, height: 30))
        self.addSubview(text2)
        super.layoutSubviews()
    }

官方建議寫法爲,約束只須要添加一次,每次調用super.updateConstraints完成約束的更新。

// This is ok! Doesn’t do anything unless self.myConstraints has been nil’d out
    override func updateConstraints() {
        if self.myConstraints == nil {
            var constraints = [NSLayoutConstraint]()
            let views = ["text1":text1, "text2":text2]
            constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|-[text1]-[text2]",
                                                          options: [.alignAllFirstBaseline],
                                                          metrics: nil,
                                                          views: views)
            constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|-[text1]-|",
                                                          options: [],
                                                          metrics: nil,
                                                          views: views)
        }
        NSLayoutConstraint.activate(constraints)
        self.myConstraints = constraints
        super.updateConstraints()
    }

render loop有很強的特定性,它的好處能夠避免一些重複性的工做。可是它也很危險,由於它調用的頻率會很高,是很是敏感的一段代碼。

蘋果建議使用interface builder進行佈局。

 

WX20180619-160810.png

激活一個約束

在設置約束的時候發生了什麼事情呢?從下面的圖中能夠看到總體的一個結構。
有一個view 在window上,window上面有個叫作engine的內部對象,engine是autolayout計算的核心,當添加一個約束的時候,會建立一個Equation對象,而後會把equation對象添加到engine上,equation依據variables對象。

 

WX20180619-160848.png

variables至關於每個約束的值,好比說一個UIlabel有四個約束minX minY width height那麼minX minY width height 就是variables。

 

WX20180619-160919.png

如下面這個圖爲例,這裏只關注水平方向的佈局,首先要建立equation,而後每個equation會添加給engine。

 

WX20180619-161418.png

engine會去計算這些variables,engine會把每個view的variables用數學公式計算出一個定量。

 

WX20180619-161501.png

計算出定量以後,engine會發送通知,通知view調用他父view的setNeedsLayout()方法,就會完成render loop的第一步更新約束,而後繼續render loop的 layout更新,最後view會直接拷貝engine計算好的定量進行賦值渲染。

 

WX20180619-161533.png

engine是一個layout的緩存,和依賴的追蹤器。很是有方向性的,它知道哪些約束會影響哪些view,當你改變一些約束時,它可以準確的更新。

不須要的約束不要加

你也能夠穿過層級,爲兩個沒有相同父view的view設置約束,可是這樣性能會不好。
大多數狀況下,view的約束應該加在他的父view或者兄弟view上。

 

WX20180619-161603.png

最小限度的錯誤

當view向engine獲取約束的值的時候,engine會確保錯誤率最小

 

WX20180619-161637.png

構建高性能layout

建立一個layout

構建一個社交軟件的cell,經過autolayout進行佈局。

 

WX20180619-161704.png

查找代碼中的問題

下面是beta版的一個調試工具,最上面第一項表示你CPU的使用狀況,峯值的地方可能須要關注一下你的layout是否有性能問題,下面一行追蹤你的約束,高的地方說明是有問題的。
第二項是你對約束添加、刪除、修改等操做的記錄。
第三項是當前控件的大小。

WX20180619-161733.png

點擊約束峯值的地方能夠看詳情。

建立高性能的佈局

經過instrument調試工具,能夠看出一些佈局上的耗時問題。一下是須要注意的幾點:

  • 避免刪除全部的約束的狀況
  • 對於靜態約束,只須要添加一次
  • 只改變須要改變的約束
  • 儘可能用hide() 方法隱藏view,而不是remove而後在add

有些控件比較特殊,好比 UIImageView,它的大小是根據他的image計算肯定他的content size。UILabel是根據他的text肯定的。這些都會返回它們的固有尺寸,UIView 會直接經過他們的固有尺寸來當作約束條件。

重寫 intrinsicContentSize

text的計算是成本很高的,因此UIlabel的size經過text去控制計算開銷成本會很高。這個時候咱們能夠 經過重寫 UILabel 的 intrinsicContentSize 來直接控制它的固有尺寸。若是已知一個UILabel的展現size,直接重寫其屬性,其餘狀況使用UIView.noIntrinsicMetric。

override var intrinsicContentSize: CGSize {
    return CGSize(width: UIView.noIntrinsicMetric, height: UIVie
相關文章
相關標籤/搜索