IOS布局淺析

理解Update Cycle摘自《[譯] 揭秘 iOS 布局》

UPdate Cycle是當應用完成了你所有的事件處理代碼之后回到主RunLoop時的時間點挺尾。正是在這個時間點上開始更新布局烦周、顯示和設置約束。如果你在處理事件的代碼中請求修改了一個view,那么系統(tǒng)會把這個view標記為重畫卿叽。接下來的Update cycle中床佳,系統(tǒng)就會執(zhí)行view的更改滋早。用戶交互和布局更新的延遲幾乎不會被用戶察覺到,IOS一般以60fps的速度展示動畫砌们,也就是一個周期大概是1/60s杆麸。這個更新過程很快,用戶也很難察覺到浪感。所以用戶察覺不到UI中更新的延遲昔头,但是由于處理事件和對應view重畫中間存在著間隔,RunLoop中某時刻的view更新可能不是你想要的那樣影兽。如果你的代碼中的某些設計依賴于當下的view內(nèi)容或者布局揭斧,那么就有在過時view信息上操作的風險。

意思就是當我們代碼更新view的布局的時候峻堰,界面上的UI并不會馬上更新讹开,而是會在下一次Update Cycle的時候更新盅视。

layoutSubviews()

這個方法的作用其實就是通知當前的view你的布局發(fā)生變化了,你要重新布局你的subviews萧吠,該方法不要手動調(diào)用左冬,系統(tǒng)會在需要調(diào)用的時候自動調(diào)用。如下幾種情況會觸發(fā) layoutSubviews()

  • 修改view的大小
  • 新增subview
  • 用戶在UIScrollView上滾動
  • 旋轉(zhuǎn)屏幕
  • 更新視圖的約束

setNeedsLayout()

顧名思義需要設置布局纸型,就是告訴系統(tǒng)這個視圖需要更新布局,這個方法會立即返回梅忌,但是view會在下一次Update cycle中更新狰腌,調(diào)用視圖們的layoutSubviews()


layoutIfNeeded()

layoutIfNeeded()不一定會觸發(fā)view的layoutSubviews牧氮。系統(tǒng)會檢測layoutSubviews的觸發(fā)條件琼腔,如果符合條件,那么會立即觸發(fā)layoutSubviews()踱葛,不會像setNeedsLayout()等待下一次Update cycle丹莲。如果不符合layoutSubviews的觸發(fā)條件則不會觸發(fā)。
這里可以解釋自動布局在開始執(zhí)行動畫的時候為什么必須執(zhí)行setNeedsLayout()尸诽,如果不添加setNeedsLayout()不會執(zhí)行動畫甥材。
如下代碼的結果是2s之后無動畫。

    self.viewOne = [[TestViewOne alloc] initWithFrame:CGRectZero];
    self.viewOne.backgroundColor = UIColor.redColor;
    [self.view addSubview:self.viewOne];
    [self.viewOne mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.mas_equalTo(self.view);
        make.width.mas_equalTo(100);
        make.height.mas_equalTo(100);
    }];
      
    [UIView animateWithDuration:2 animations:^{
            [self.viewOne mas_remakeConstraints:^(MASConstraintMaker *make) {
                make.center.mas_equalTo(self.view);
                make.width.mas_equalTo(50);
                make.height.mas_equalTo(50);
            }];
           NSLog(@"動畫打印viewOne的frame%@",NSStringFromCGRect(self.viewOne.frame));
        }];
//打印結果
2019-03-13 17:44:27.115060+0800 layoutStudy[16692:523774] 動畫打印viewOne的frame{{182, 423}, {100, 100}}

如果添加進去layoutIfNeeded()性含;

    self.viewOne = [[TestViewOne alloc] initWithFrame:CGRectZero];
    self.viewOne.backgroundColor = UIColor.redColor;
    [self.view addSubview:self.viewOne];
    [self.viewOne mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.mas_equalTo(self.view);
        make.width.mas_equalTo(100);
        make.height.mas_equalTo(100);
    }];
      
    [UIView animateWithDuration:2 animations:^{
            [self.viewOne mas_remakeConstraints:^(MASConstraintMaker *make) {
                make.center.mas_equalTo(self.view);
                make.width.mas_equalTo(50);
                make.height.mas_equalTo(50);
            }];
          [self.viewOne layoutIfNeeded];
           NSLog(@"動畫打印viewOne的frame%@",NSStringFromCGRect(self.viewOne.frame));
     }];
//打印結果
2019-03-13 17:44:27.115060+0800 layoutStudy[16692:523774] 動畫打印viewOne的frame{{182, 423}, {50, 50}}

其實自動布局也是通過一套引擎轉(zhuǎn)換成frame洲赵,但是這個過程并不是馬上進行的會在下一次Update Cycle執(zhí)行,調(diào)用layoutIfNeeded會強制計算frame繪制完畢會調(diào)用layoutSubviews商蕴,并且被animation的block截獲叠萍。可以明顯的看出代碼1中self.viewOne的frame沒有變绪商,但是代碼2的frame被提前繪制出來了苛谷,所以代碼2有動畫,代碼1沒有動畫格郁。


總結

那么我們的布局代碼應該怎么寫呢腹殿,我覺得不改變的靜態(tài)布局直接在init的時候?qū)懢涂梢裕雅c自身視圖尺寸有依賴的約束寫到里面理张,由于layoutSubviews可能會多次調(diào)用赫蛇。不要在其中寫比較耗時的操作和初始化對象。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末雾叭,一起剝皮案震驚了整個濱河市悟耘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌织狐,老刑警劉巖暂幼,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件筏勒,死亡現(xiàn)場離奇詭異,居然都是意外死亡旺嬉,警方通過查閱死者的電腦和手機管行,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來邪媳,“玉大人捐顷,你說我怎么就攤上這事∮晷В” “怎么了迅涮?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長叮姑。 經(jīng)常有香客問我据悔,道長极颓,這世上最難降的妖魔是什么托享? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任羡榴,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布积仗。 她就那樣靜靜地躺著回右,像睡著了一般旨涝。 火紅的嫁衣襯著肌膚如雪弧腥。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天,我揣著相機與錄音纠亚,去河邊找鬼骗随。 笑死涨椒,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的疙教。 我是一名探鬼主播躺屁,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼经宏!你這毒婦竟也來了犀暑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤烁兰,失蹤者是張志新(化名)和其女友劉穎耐亏,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沪斟,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡广辰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年暇矫,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片择吊。...
    茶點故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡李根,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出几睛,到底是詐尸還是另有隱情房轿,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布所森,位于F島的核電站囱持,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏焕济。R本人自食惡果不足惜纷妆,卻給世界環(huán)境...
    茶點故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望晴弃。 院中可真熱鬧掩幢,春花似錦、人聲如沸上鞠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽旗国。三九已至,卻和暖如春注整,著一層夾襖步出監(jiān)牢的瞬間能曾,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工肿轨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留寿冕,地道東北人。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓椒袍,卻偏偏與公主長得像驼唱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子驹暑,可洞房花燭夜當晚...
    茶點故事閱讀 45,435評論 2 359

推薦閱讀更多精彩內(nèi)容