iOS - AutoLayout

1. AutoLayout的核心

蘋果公司推出的AutoLayout粪牲,是一個基于約束,動態(tài)計算視圖大小和位置的庫帕胆,以布局引擎系統(tǒng)Layout Engine為核心轴捎,采用了 Cassowary布局算法,在簡化布局思路的同時百炬,還保證了布局的高效性褐隆。

布局算法Cassowary能夠有效解析線性等式系統(tǒng)和線性不等式系統(tǒng),用來表示用戶界面中那些相等關(guān)系和不等關(guān)系剖踊,通過設(shè)定約束來表示一個視圖相對于另一個視圖的位置庶弃。

Cassowary簡化了布局思路,在運行時動態(tài)的計算視圖位置德澈。布局思路簡化了歇攻,也使界面相關(guān)代碼更容易維護。

布局引擎系統(tǒng)Layout Engine則統(tǒng)一管理了布局的創(chuàng)建梆造、更新缴守、銷毀,將視圖的約束镇辉、優(yōu)先級屡穗、固定大小通過計算轉(zhuǎn)換成最終的大小和位置。

在Layout Engine中忽肛,每當(dāng)約束發(fā)生變化村砂,會重新計算布局,獲取到布局后調(diào)用superview.setNeedLayout()麻裁,然后觸發(fā)Deffered Layout Pass做容錯處理箍镜,然后Layout Engine會從上到下調(diào)用layoutSubviews()來確定各子視圖的位置(通過Cassowary算法計算)源祈,算出來后將子視圖的frame從Layout Engine里拷貝出來,然后進行繪制色迂、渲染香缺,得到我們眼中看到的UI效果。

  • 總結(jié):AutoLayout利用約束來控制視圖的大小和位置歇僧,系統(tǒng)會在運行時通過設(shè)置的約束計算得到frame图张,然后繪制出來顯示。

2. AutoLayout的性能

在iOS12之前诈悍,AutoLayout在處理多層級嵌套時祸轮,開銷呈指數(shù)級躍增,但是從iOS12開始侥钳,蘋果補齊了這一漏洞适袜,所以在iOS12及以后,我們就開始放心的使用AutoLayout舷夺,而不用擔(dān)心性能問題苦酱。

更多關(guān)于AutoLayout的性能問題及解決方法,請查看WWDC2018-202

AutoLayout在iOS12中的表現(xiàn).png

3. AutoLayout常見的問題

(1)幾個更新方法的區(qū)別
  • setNeedsLayout:告知頁面需要更新给猾,但是不會立刻開始更新疫萤。

  • layoutIfNeeded:如果有需要刷新的標記,立即調(diào)用layoutSubviews進行布局敢伸;如果沒有標記扯饶,不會調(diào)用layoutSubviews。如果希望立刻生成新的frame需要調(diào)用此方法池颈,利用這點一般布局動畫可以在更新布局后直接使用這個方法讓動畫生效尾序。

  • layoutSubviews:對subviews進行布局,不能主動調(diào)用饶辙,需要的時候在子類重寫蹲诀,系統(tǒng)會在合適的時候自動調(diào)用。

  • 注意 : 如果要立即刷新frame弃揽,要先調(diào)用setNeedsLayout()脯爪,把標記設(shè)為需要布局,然后馬上調(diào)用layoutIfNeeded()矿微,實現(xiàn)布局痕慢。

  • setNeedsUpdateConstraints:告知需要更新約束,但是不會立刻開始

  • updateConstraintsIfNeeded:告知立刻更新約束

  • updateConstraints:系統(tǒng)更新約束

(2)系統(tǒng)調(diào)用layoutSubviews的時機
  • init初始化不會觸發(fā)layoutSubviews涌矢,但是使用initWithFrame進行初始化且rect不為zero時掖举,會調(diào)用layoutSubviews。

  • addSubview的時候會觸發(fā)系統(tǒng)調(diào)用layoutSubviews娜庇。

  • 當(dāng)view的frame發(fā)生改變的時候觸發(fā)layoutSubviews塔次。

  • 滾動一個UIScrollView會觸發(fā)layoutSubviews方篮。

  • 旋轉(zhuǎn)Screen會觸發(fā)父UIView上的layoutSubviews事件。

  • 改變一個UIView大小的時候也會調(diào)用父UIView上的layoutSubviews事件励负。

(3)Intrinsic content size 固有內(nèi)容大小
  • Intrinsic content size 就是固有內(nèi)容大小藕溅,對應(yīng)的系統(tǒng)方法是intrinsicContentSize,重寫UIView的固有內(nèi)容大小后继榆,我們就可以更靈活的使用UIView了巾表。

  • 在xib中想使用Intrinsic Size時,記得先在子類中重寫intrinsicContentSize略吨,然后在Xib選中Placeholder集币,才不會報錯哦。

class TestView: UIView {
    override var intrinsicContentSize: CGSize {
        return CGSize(width: 300, height: 800)
    }
}
(4)手寫autoLayout翠忠,寫在哪里最好
  • 如果是自定義的View鞠苟,寫在init()方法中

  • 如果是在ViewController中,寫在viewDidLoad()

(5)SizeClass適配

關(guān)于SizeClass负间,請看我的另一篇簡書適配iPad和iPhone及其橫豎屏

(6)UIStackView

對一些特定布局時偶妖,使用UIStackView很節(jié)省時間,iOS9.0之后可用


StackView.png
  • Axis : 子控件的布局方向政溃,水平或垂直
  • Alignment :子控件對齊方式
  • Distribution : 子控件分布方式
  • Spacing : 控件和控件之間的最小間距
(7)UITableView的高度計算
  • 手工計算,并緩存高度
    從xib中加載一個Cell态秧,然后給這個Cell中的控件賦值董虱,然后利用systemLayoutSizeFitting計算高度,然后緩存高度到Model中
  let tableViewCell = Bundle.main.loadNibNamed("tableViewCell", owner: self, options: nil)?.last
  //先給給tablViewCell中的控件賦值申鱼,然后在計算高度
  if let tableViewCell = tableViewCell as? UITableViewCell{
       let cellSize = tableViewCell.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
  }
  //然后在緩存高度到Model中
  • 使用Self-Sizing自動計算高度愤诱,當(dāng)布局滿足self-satisfied時,系統(tǒng)會自動計算高度捐友,缺點是慢淫半,因為沒有緩存高度,每次都要計算一次
tableView.estimatedRowHeight = 300
tableView.rowHeight = UITableView.automaticDimension
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末匣砖,一起剝皮案震驚了整個濱河市科吭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌猴鲫,老刑警劉巖对人,帶你破解...
    沈念sama閱讀 212,080評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異拂共,居然都是意外死亡牺弄,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評論 3 385
  • 文/潘曉璐 我一進店門宜狐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來势告,“玉大人蛇捌,你說我怎么就攤上這事≡厶ǎ” “怎么了豁陆?”我有些...
    開封第一講書人閱讀 157,630評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吵护。 經(jīng)常有香客問我盒音,道長,這世上最難降的妖魔是什么馅而? 我笑而不...
    開封第一講書人閱讀 56,554評論 1 284
  • 正文 為了忘掉前任祥诽,我火速辦了婚禮,結(jié)果婚禮上瓮恭,老公的妹妹穿的比我還像新娘雄坪。我一直安慰自己,他們只是感情好屯蹦,可當(dāng)我...
    茶點故事閱讀 65,662評論 6 386
  • 文/花漫 我一把揭開白布维哈。 她就那樣靜靜地躺著,像睡著了一般登澜。 火紅的嫁衣襯著肌膚如雪阔挠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,856評論 1 290
  • 那天脑蠕,我揣著相機與錄音购撼,去河邊找鬼。 笑死谴仙,一個胖子當(dāng)著我的面吹牛迂求,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晃跺,決...
    沈念sama閱讀 39,014評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼揩局,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了掀虎?” 一聲冷哼從身側(cè)響起凌盯,我...
    開封第一講書人閱讀 37,752評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎涩盾,沒想到半個月后十气,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,212評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡春霍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,541評論 2 327
  • 正文 我和宋清朗相戀三年砸西,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,687評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡芹枷,死狀恐怖衅疙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情鸳慈,我是刑警寧澤饱溢,帶...
    沈念sama閱讀 34,347評論 4 331
  • 正文 年R本政府宣布,位于F島的核電站走芋,受9級特大地震影響绩郎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜翁逞,卻給世界環(huán)境...
    茶點故事閱讀 39,973評論 3 315
  • 文/蒙蒙 一肋杖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧挖函,春花似錦状植、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至必怜,卻和暖如春肉拓,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背棚赔。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評論 1 266
  • 我被黑心中介騙來泰國打工帝簇, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人靠益。 一個月前我還...
    沈念sama閱讀 46,406評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像残揉,于是被迫代替她去往敵國和親胧后。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,576評論 2 349