AutoLayout一些整理

本系列博客是本人的開發(fā)筆記。為了方便討論,本人新建了一個(gè)微信群(iOS技術(shù)討論群),想要加入的,請(qǐng)?zhí)砑颖救宋⑿牛簔hujinhui207407,【加我前請(qǐng)備注:iOS 】,本人博客http://www.kyson.cn 也在不停的更新中,歡迎一起討論

引言

在WWDC2018中,展示了iOS12對(duì)AutoLayout優(yōu)化,UICollectionView性能對(duì)比,item自動(dòng)適配大小,iOS 11看上去有掉幀卡頓的現(xiàn)象,iOS 12表現(xiàn)完美,沒有掉幀。


ios12優(yōu)化

初識(shí) Auto Layout

Auto Layout 的原理其實(shí)非常簡(jiǎn)單,在這里通過一個(gè)例子先簡(jiǎn)單的解釋一下:


autolayout

iOS 中視圖所需要的布局信息只有兩個(gè),分別是 origin/center 和 size,在這里我們以 origin & size 為例,也就是 frame 時(shí)代下布局的需要的兩個(gè)信息;這兩個(gè)信息由四部分組成:

x & y
width & height

以左上角的 (0, 0) 為坐標(biāo)的原點(diǎn),找到坐標(biāo) (x, y),然后繪制一個(gè)大小為 (width, height) 的矩形,這樣就完成了一個(gè)最簡(jiǎn)單的布局。而 Auto Layout 的布局方式與上面所說的 frame 有些不同,frame 表示與父視圖之間的絕對(duì)距離,但是 Auto Layout 中大部分的約束都是描述性的,表示視圖間相對(duì)距離,以上圖為例:

A.left = Superview.left + 50
A.top  = Superview.top + 30
A.width  = 100
A.height = 100

B.left = (A.left + A.width)/(A.right) + 30
B.top  = A.top
B.width  = A.width
B.height = A.height

雖然上面的約束很好的表示了各個(gè)視圖之間的關(guān)系,但是 Auto Layout 實(shí)際上并沒有改變?cè)械?Hard-Coded 形式的布局方式,只是將原有沒有太多意義的 (x, y) 值,變成了描述性的代碼。

我們?nèi)匀恍枰啦季中畔⑺枰乃牟糠?x、y、width 以及 height。換句話說,我們要求解上述的八元一次方程組,將每個(gè)視圖所需要的信息解出來;Cocoa 會(huì)在運(yùn)行時(shí)求解上述的方程組,最終使用 frame 來繪制視圖。


autolayout

Auto Layout 的原理就是對(duì)線性方程組或者不等式的求解。

  • Auto Layout 的性能
    在使用 Auto Layout 進(jìn)行布局時(shí),可以指定一系列的約束,比如視圖的高度、寬度等等。而每一個(gè)約束其實(shí)都是一個(gè)簡(jiǎn)單的線性等式或不等式,整個(gè)界面上的所有約束在一起就明確地(沒有沖突)定義了整個(gè)系統(tǒng)的布局。

在涉及沖突發(fā)生時(shí),Auto Layout 會(huì)嘗試 break 一些優(yōu)先級(jí)低的約束,盡量滿足最多并且優(yōu)先級(jí)最高的約束。

因?yàn)椴季窒到y(tǒng)在最后仍然需要通過 frame 來進(jìn)行,所以 Auto Layout 雖然為開發(fā)者在描述布局時(shí)帶來了一些好處,不過它相比原有的布局系統(tǒng)加入了從約束計(jì)算 frame 的過程,而在這里,我們需要了解 Auto Layout 的布局性能如何。

性能

因?yàn)槭褂盟惴ń鉀Q約束問題就是對(duì)線性等式或不等式求解,所以其時(shí)間復(fù)雜度就是多項(xiàng)式時(shí)間的,不難推測(cè)出,在處理極其復(fù)雜的 UI 界面時(shí),會(huì)造成性能上的巨大損失。

在這里我們會(huì)對(duì) Auto Layout 的性能進(jìn)行測(cè)試,為了更明顯的展示 Auto Layout 的性能,我們通過 frame 的性能建立一條基準(zhǔn)線以消除對(duì)象的創(chuàng)建和銷毀、視圖的渲染、視圖層級(jí)的改變帶來的影響。

Layout 性能測(cè)量使用的代碼可以在筆者附帶的Demo中進(jìn)行演示獲取。

代碼分別使用 Auto Layout 和 frame 對(duì) N 個(gè)視圖進(jìn)行布局,測(cè)算其運(yùn)行時(shí)間。

使用 AutoLayout 時(shí),每個(gè)視圖會(huì)隨機(jī)選擇兩個(gè)視圖對(duì)它的 top 和 left 進(jìn)行約束,隨機(jī)生成一個(gè)數(shù)字作為 offset;同時(shí),還會(huì)用幾個(gè)優(yōu)先級(jí)高的約束保證視圖的布局不會(huì)超出整個(gè) keyWindow。

而下圖就是對(duì) 100~1000 個(gè)視圖布局所需要的時(shí)間的折線圖。

這里的數(shù)據(jù)是在 OS X EL Captain,Macbook Air (13-inch Mid 2013)上的 iPhone 6s Plus 模擬器上采集的, Xcode 版本為 7.3.1。在其他設(shè)備上可能不會(huì)獲得一致的信息,由于筆者的 iPhone 升級(jí)到了 iOS 10,所以沒有辦法真機(jī)測(cè)試,最后的結(jié)果可能會(huì)有一定的偏差。

性能

從圖中可以看到,使用 Auto Layout 進(jìn)行布局的時(shí)間會(huì)是只使用 frame 的 16 倍左右,雖然這里的測(cè)試結(jié)果可能受外界條件影響差異比較大,不過 Auto Layout 的性能相比 frame 確實(shí)差很多,如果去掉設(shè)置 frame 的過程消耗的時(shí)間,Auto Layout 過程進(jìn)行的計(jì)算量也是非常巨大的。

在上一篇文章中,我們?cè)?jīng)提到,想要讓 iOS 應(yīng)用的視圖保持 60 FPS 的刷新頻率,我們必須在 1/60 = 16.67 ms 之內(nèi)完成包括布局、繪制以及渲染等操作。

也就是說如果當(dāng)前界面上的視圖大于 100 的話,使用 Auto Layout 是很難達(dá)到絕對(duì)流暢的要求的;而在使用 frame 時(shí),同一個(gè)界面下哪怕有 500 個(gè)視圖,也是可以在 16.67 ms 之內(nèi)完成布局的。不過在一般情況下,在 iOS 的整個(gè) UIWindow 中也不會(huì)一次性出現(xiàn)如此多的視圖。

我們更關(guān)心的是,在日常開發(fā)中難免會(huì)使用 Auto Layout 進(jìn)行布局,既然有 16.67 ms 這個(gè)限制,那么在界面上出現(xiàn)了多少個(gè)視圖時(shí),我才需要考慮其它的布局方式呢?在這里,我們將需要布局的視圖數(shù)量減少一個(gè)量級(jí),重新繪制一個(gè)圖表:


性能2

從圖中可以看出,當(dāng)對(duì) 30 個(gè)左右視圖使用 Auto Layout 進(jìn)行布局時(shí),所需要的時(shí)間就會(huì)在 16.67 ms 左右,當(dāng)然這里不排除一些其它因素的影響;到目前為止,會(huì)得出一個(gè)大致的結(jié)論,使用 Auto Layout 對(duì)復(fù)雜的 UI 界面進(jìn)行布局時(shí)(大于 30 個(gè)視圖)就會(huì)對(duì)性能有嚴(yán)重的影響(同時(shí)與設(shè)備有關(guān),文章中不會(huì)考慮設(shè)備性能的差異性)。

上述對(duì) Auto Layout 的使用還是比較簡(jiǎn)單的,而在日常使用中,使用嵌套的視圖層級(jí)又非常正常。

在筆者對(duì)嵌套視圖層級(jí)中使用 Auto Layout 進(jìn)行布局時(shí),當(dāng)視圖的數(shù)量超過了 500 時(shí),模擬器直接就 crash 了,所以這里沒有超過 500 個(gè)視圖的數(shù)據(jù)。

我們對(duì)嵌套視圖數(shù)量在 100~500 之間布局時(shí)間進(jìn)行測(cè)量,并與 Auto Layout 進(jìn)行比較:

性能3

在視圖數(shù)量大于 200 之后,隨著視圖數(shù)量的增加,使用 Auto Layout 對(duì)嵌套視圖進(jìn)行布局的時(shí)間相比非嵌套的布局成倍增長(zhǎng)。

雖然說 Auto Layout 為開發(fā)者在多尺寸布局上提供了遍歷,而且支持跨越視圖層級(jí)的約束,但是由于其實(shí)現(xiàn)原理導(dǎo)致其時(shí)間復(fù)雜度為多項(xiàng)式時(shí)間,其性能損耗是僅使用 frame 的十幾倍,所以在處理龐大的 UI 界面時(shí)表現(xiàn)差強(qiáng)人意。

iOS優(yōu)化實(shí)現(xiàn)

  • Render Loop
    Render Loop 是一個(gè)每秒鐘跑120次的一個(gè)進(jìn)程,是為了確保所有的內(nèi)容都能為每一個(gè)frame做好準(zhǔn)備。Render Loop 一共包括三個(gè)步驟來更新約束,布局和渲染。

首先,每一個(gè)需要接收到更新約束的view會(huì)從子view向上傳遞,直到window;
然后,每一個(gè)接收到的view開始layoutsubviews,和更新約束是從相反的方向開始,layout從window開始到每一個(gè)子view進(jìn)行l(wèi)ayout。
最后,每一個(gè)需要渲染的view,和layout相同,從父view向子view開始渲染。

優(yōu)化

Render Loop目的是為了避免重復(fù)的工作。
舉一個(gè)例子:一個(gè)UILable 需要一個(gè)約束來描述它的大小,但是有很多屬性會(huì)影響他的大小,設(shè)置它的font,text size等等都會(huì)受到影響。當(dāng)一個(gè)屬性改變的時(shí)候,可能text其他屬性也會(huì)被重新賦值
,很有可能調(diào)用一堆屬性的setter方法,這樣效率會(huì)很低。
只需要調(diào)用updateConstraints 并指定好要更新的屬性,Render Loop會(huì)幫助你計(jì)算好它的frame并完成渲染,從而避免多次設(shè)置的重復(fù)工作。

展示

Auto Layout 以外的優(yōu)化

iOS 12 比 iOS 11 更快、更平滑了,升級(jí)了的朋友肯定都同意這一點(diǎn)。但蘋果為了讓 iOS 12 變快究竟做了哪些升級(jí)呢,蘋果為我們介紹了針對(duì) iOS 12 做出的一系列改變。

  • 改進(jìn)預(yù)加載功能
    在 iOS 12 中,蘋果工程師攻克了困擾用戶數(shù)年的卡頓問題,他們?cè)跈z查官方 App 時(shí)發(fā)現(xiàn)了過去丟幀的原因。在 iOS 中,用戶滑動(dòng)、點(diǎn)擊屏幕的時(shí)候就需要即時(shí)渲染生成內(nèi)容,比如說菜單列表或者是文檔中的圖形,這個(gè)生成的過程花費(fèi)的時(shí)間就會(huì)導(dǎo)致延遲。為了降低這一延遲,蘋果在 iOS 10 中引入了一個(gè)名為“Cell Pre-fetch”的功能,簡(jiǎn)單來說就是在后臺(tái)預(yù)測(cè)用戶的動(dòng)作,然后預(yù)先加載好相應(yīng)的內(nèi)容,當(dāng)用戶確定了這個(gè)點(diǎn)擊或滑動(dòng)馬上把預(yù)加載好的內(nèi)容呈現(xiàn)上來,這樣一來就不會(huì)延遲了,而且不會(huì)出現(xiàn)處理器負(fù)載突然加大的問題。雖然“Cell Pre-fetch”確實(shí)讓 iOS 10 變快了,但是仍然沒有完全解決丟幀問題,工程師們發(fā)現(xiàn),當(dāng)系統(tǒng)在預(yù)加載內(nèi)容的時(shí)候,處理器也同時(shí)在渲染確定會(huì)在屏幕上呈現(xiàn)的那一組內(nèi)容,二者同時(shí)進(jìn)行就會(huì)導(dǎo)致 CPU 遇到瓶頸,然后兩個(gè)任務(wù)就都變慢了。為了解決這一問題,蘋果在 Cocoa Touch (開發(fā)者創(chuàng)建 iOS App 時(shí)使用的接口)中重新對(duì)任務(wù)進(jìn)行了排序,在屏幕渲染任務(wù)完成之后,預(yù)加載才啟動(dòng),因?yàn)榍罢咝枰R上被用戶看到,更加重要。

  • CPU響應(yīng)機(jī)制升級(jí)
    除了這一點(diǎn)之外,CPU 也有一定的升級(jí)。此前的 iOS 設(shè)備中,在 CPU 負(fù)載很小的時(shí)候也會(huì)發(fā)生丟幀,因?yàn)樵谌蝿?wù)很少的時(shí)候 CPU 會(huì)降低頻率進(jìn)入怠速模式。但是如果用戶突然觸發(fā)了一個(gè)比較麻煩的任務(wù),CPU 就需要一點(diǎn)時(shí)間反應(yīng)過來然后加快頻率,這一過程中就會(huì)發(fā)生延遲。而在 iOS 12 中,蘋果優(yōu)化了 CPU 的響應(yīng)機(jī)制,能更快地從低頻提升到高頻,并且 iOS 12 還很聰明,不會(huì)把 CPU 的頻率拉得太高,只會(huì)提供完成這個(gè)任務(wù)所需要的那個(gè)頻率上,所以在完成任務(wù)之后,CPU 也能夠很快將頻率降到合適的怠速水平,減少電池的消耗。

  • Auto-layout (自動(dòng)布局)功能升級(jí)
    緊接著還有對(duì) Auto-layout (自動(dòng)布局)功能的升級(jí),Auto-layout 讓開發(fā)者能對(duì) App 內(nèi)的圖標(biāo)、文字等元素更方便地定位(比如據(jù)邊框多少像素),以適應(yīng)不同的屏幕尺寸。但是蘋果工程師發(fā)現(xiàn)這個(gè)從 iOS 6 就有的功能現(xiàn)在看來有些過于耗費(fèi)資源了,在不同的情況下, Auto-layout 使用的資源可能會(huì)呈指數(shù)級(jí)增長(zhǎng),比如元素在嵌套和依賴于其他元素進(jìn)行放置兩種狀態(tài)下,耗費(fèi)的資源大不相同。在 iOS 12 中,蘋果大大減少了會(huì)導(dǎo)致指數(shù)縮放的元素,減輕了對(duì) CPU 和 GPU 的負(fù)擔(dān)??傮w來看,讓渲染的元素彼此獨(dú)立放置、互不干擾能夠減少資源消耗。

  • 自動(dòng)備份存儲(chǔ)技術(shù)
    最后,蘋果還介紹了 iOS 12 的自動(dòng)備份存儲(chǔ)技術(shù),它可以減少應(yīng)用程序運(yùn)行的時(shí)候消耗的內(nèi)存量。在蘋果的演示中,當(dāng)舊版系統(tǒng)渲染相同大小的彩色照片和灰度圖像(只存在灰度信息的黑白照片)時(shí),耗費(fèi)的內(nèi)存竟然是完全一樣的,但其實(shí)這兩張照片包含的信息存在顯著差異,彩色照片每個(gè)像素都有色值等信息,黑白照片只有灰度信息。而在使用自動(dòng)備份存儲(chǔ)技術(shù)之后,系統(tǒng)會(huì)對(duì)不同文件包含的數(shù)值信息進(jìn)行一個(gè)初步的判斷,然后再分配合適的內(nèi)存給它,不會(huì)像以前那樣一視同仁地處理所有內(nèi)容,這樣做顯然可以避免浪費(fèi)內(nèi)存資源。

除了以上四點(diǎn)之外,蘋果還介紹了不少加快系統(tǒng)運(yùn)作的方法。不過在演講的最后,工程師還是表示現(xiàn)在他們正在積極地對(duì)這些功能展開工作,希望在 iOS 12 正式版上線之前(今年九月)完成優(yōu)化,如果無法完成,可能會(huì)推遲幾個(gè)版本。

AutoLayout 基礎(chǔ)知識(shí)

Autolayout是IOS6以后才出現(xiàn)的新技術(shù),比f(wàn)rame使用更加地方便,比Autoresizing更加地強(qiáng)大。下面,就介紹一下在項(xiàng)目開發(fā)中使用Autolayout幾種途徑。

純代碼實(shí)現(xiàn)Autolayout

  • NSLayoutConstraint
[NSLayoutConstraint constraintWithItem:(id)item attribute:(NSLayoutAttribute)attribute relatedBy:(NSLayoutRelation)relation toItem:(id)otherItem attribute:(NSLayoutAttribute)otherAttribute multiplier:(CGFloat)multiplier constant:(CGFloat)constant]

舉個(gè)簡(jiǎn)單的例子,我們?cè)谒赾ontroller默認(rèn)view上添加一個(gè)子視圖subview,subview的寬高為view寬高的1/3,距離view左邊100,距離view上邊150,就可以用下面代碼這樣實(shí)現(xiàn):

UIView *subView = [[UIView alloc]init];
subView.backgroundColor = [UIColor greenColor];
[self.view addSubview:subView];
subView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1. constant:150]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:0.3 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0.3 constant:0]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:subView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1. constant:100]];

上面方法參數(shù)說明:
第一個(gè)參數(shù):指定約束左邊的視圖view1
第二個(gè)參數(shù):指定view1的屬性attr1
第三個(gè)參數(shù):指定左右兩邊的視圖的關(guān)系relation
第四個(gè)參數(shù):指定約束右邊的視圖view2
第五個(gè)參數(shù):指定view2的屬性attr2
第六個(gè)參數(shù):指定一個(gè)與view2屬性相乘的乘數(shù)multiplier
第七個(gè)參數(shù):指定一個(gè)與view2屬性相加的浮點(diǎn)數(shù)constant
依據(jù)的公式是:view1.attr1 = view2.attr2*multiplier +constant

NSLayoutAttribute的類型:
NSLayoutAttributeLeft 視圖的左邊
NSLayoutAttributeRight 視圖的右邊
NSLayoutAttributeTop 視圖的上邊
NSLayoutAttributeBottom 視圖的下邊
NSLayoutAttributeLeading 視圖的前邊
NSLayoutAttributeTrailing 視圖的后邊
NSLayoutAttributeWidth 視圖的寬度
NSLayoutAttributeHeight 視圖的高度
NSLayoutAttributeCenterX 視圖的中點(diǎn)的X值
NSLayoutAttributeCenterY 視圖中點(diǎn)的Y值
NSLayoutAttributeBaseline 視圖的基準(zhǔn)線
NSLayoutAttributeNotAnAttribute 無屬性

NSLayoutRelation的類型:
NSLayoutRelationLessThanOrEqual 關(guān)系小于或等于
NSLayoutRelationEqual 視圖關(guān)系等于
NSLayoutRelationGreaterThanOrEqual 視圖關(guān)系大于或等于
這里要說明一下,設(shè)置約束之前必須要求確保子視圖添加到了父視圖上了(如:[self.view addSubview:subView]),并且被約束的視圖的translatesAutoresizingMaskIntoConstraints = NO,不然就會(huì)發(fā)生程序crash。

  • VFL(Visual format language)
    VFL是NSLayoutConstraint使用特定的NSString類型字符串來創(chuàng)建Constraint,通過下面方法就可以創(chuàng)建
[NSLayoutConstraint 
 constraintsWithVisualFormat:(NSString *)format options:(NSLayoutFormatOptions)opts metrics:(nullable NSDictionary<NSString *,id> *)metrics views:(NSDictionary<NSString *, id> *)views]

關(guān)于VFL格式使用規(guī)則,可以參考這篇博客http://blog.csdn.net/mmoaay/article/details/46707103

  • Masonry
    通過上面的NSLayoutConstraint使用可以發(fā)現(xiàn),每次添加一條約束就要寫一長(zhǎng)串的代碼,如果視圖約束很多的話,那么就要寫很多的代碼,所以就有人基于NSLayoutConstraints進(jìn)行了封裝。Masonry就是基于NSLayoutConstraints封裝的輕量級(jí)的第三方開源框架之一。所以實(shí)例可以通過Masonry實(shí)現(xiàn):
UIView *subView = [[UIView alloc]init];
 subView.backgroundColor = [UIColor greenColor];
 [self.view addSubview:subView];
  __weak typeof(self) weakSelf = self;
 [subView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(@100);
        make.top.mas_equalTo(@150);
        make.width.mas_equalTo(weakSelf.view.mas_width).multipliedBy(0.3);
        make.height.mas_equalTo(weakSelf.view.mas_height).multipliedBy(0.3);
 }];

xib 中Autolayout設(shè)置

在xib中使用Autolayout,是一種非常直觀,非常方便的一種方式。我們可以在不用代碼就可以實(shí)現(xiàn)各種布局。


xib

按照?qǐng)D中所示,可以很快的設(shè)置子視圖Top,Leading,Bottom,Trailing的約束,切換到導(dǎo)航欄Show the size inspect按鈕可以看到已經(jīng)設(shè)置好的各個(gè)約束,并且可以對(duì)設(shè)置好約束進(jìn)行修改,如修改每個(gè)約束中constant,priority,multiplier值等。

當(dāng)然,不管是純代碼實(shí)現(xiàn)Autolayout還是xib實(shí)現(xiàn)Autolayout,都可能遇到約束沖突的情況。比如,一個(gè)subview子視圖基于父視圖設(shè)置了Top,Leading,Bottom,Trailing四個(gè)約束,并且又設(shè)置了subview的高度height,這樣運(yùn)行就是出現(xiàn)Probably at least one of the constraints in the following list is one you don't want. 的警告,因?yàn)閟ubview子視圖高度height約束和Top或Bottom產(chǎn)生了沖突。
約束沖突可以通過修改Autolayout約束的優(yōu)先級(jí)不同的方式進(jìn)行解決,在Autolayout中每個(gè)約束都有一個(gè)優(yōu)先級(jí)priority,priority的范圍是1 ~ 1000,默認(rèn)創(chuàng)建的約束priority最高是1000,并且系統(tǒng)默認(rèn)提供了Required(1000)、High(750)、Low(250)三種priority。所以對(duì)于上述subview子視圖產(chǎn)生的約束沖突問題,可以通過修改subview 子視圖Top或Bottom約束的priority小于1000就可以解決沖突問題。

創(chuàng)建高性能的布局

通過instrument調(diào)試工具,可以看出一些布局上的耗時(shí)問題。一下是需要注意的幾點(diǎn):

  • 避免刪除所有的約束的情況
  • 對(duì)于靜態(tài)約束,只需要添加一次
  • 只改變需要改變的約束
  • 盡量用hide() 方法隱藏view,而不是remove然后在add
  • 有些控件比較特殊,比如 UIImageView,它的大小是根據(jù)他的image計(jì)算確定他的content size。UILabel是根據(jù)他的text確定的。這些都會(huì)返回它們的固有尺寸,UIView 會(huì)直接通過他們的固有尺寸來當(dāng)做約束條件。
  • 重寫 intrinsicContentSize text的計(jì)算是成本很高的,所以UIlabel的size通過text去控制計(jì)算開銷成本會(huì)很高。這個(gè)時(shí)候我們可以 通過重寫 UILabel 的 intrinsicContentSize 來直接控制它的固有尺寸。如果已知一個(gè)UILabel的展示size,直接重寫其屬性,其他情況使用UIView.noIntrinsicMetric。
override var intrinsicContentSize: CGSize {
    return CGSize(width: UIView.noIntrinsicMetric, height: UIView.noIntrinsicMetric)
}

Auto Layout 原理

一般大家都會(huì)認(rèn)為Auto Layout這個(gè)東西是蘋果自己搞出來的,其實(shí)不然,早在1997年Alan Borning, Kim Marriott, Peter Stuckey等人就發(fā)布了《Solving Linear Arithmetic Constraints for User Interface Applications》論文
(論文地址:http://constraints.cs.washington.edu/solvers/uist97.html)
提出了在解決布局問題的Cassowary constraint-solving算法實(shí)現(xiàn),并且將代碼發(fā)布在他們搭建的Cassowary網(wǎng)站上
http://constraints.cs.washington.edu/cassowary/
后來更多開發(fā)者用各種語(yǔ)言來寫Cassowary,比如說pybee用python寫的
https://github.com/pybee/cassowary
自從它發(fā)布以來JavaScript,.NET,JAVA,Smalltall和C++都有相應(yīng)的庫(kù)。2011年蘋果將這個(gè)算法運(yùn)用到了自家的布局引擎中,美其名曰Auto Layout。

Cassowary 算法

在上世紀(jì) 90 年代,一個(gè)名叫 Cassowary 的布局算法解決了用戶界面的布局問題,它通過將布局問題抽象成線性等式和不等式約束來進(jìn)行求解。

Auto Layout 其實(shí)就是對(duì) Cassowary 算法的一種實(shí)現(xiàn),但是這里并不會(huì)對(duì)它展開介紹,有興趣的讀者可以在文章最后的 Reference 中了解一下 Cassowary 算法相關(guān)的文章。

引用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,688評(píng)論 4 61
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,688評(píng)論 1 32
  • 已經(jīng)17天沒日更了,我卻覺得比以前更開心了。 這17天里,我出差了一周,出差回來之后的一周調(diào)整了健身計(jì)劃,爽爽的練...
    滿滿的爸爸閱讀 258評(píng)論 0 0
  • 火車上看了尼古拉斯凱奇演的預(yù)見未來 如果人可以預(yù)見未來生活會(huì)很穩(wěn)定 如果人可以預(yù)見未來那么他不會(huì)為生存擔(dān)憂 如果人...
    從心寒閱讀 435評(píng)論 0 1
  • 寫在前面 我常常覺得生活平淡無奇,但每每想到生活中“思”的故事,就覺得那仿佛是部狗血的偶像劇,越是狗血,仿佛越是真...
    勿執(zhí)念閱讀 283評(píng)論 0 0

友情鏈接更多精彩內(nèi)容