iOS進(jìn)階之masonry細(xì)致入微(二)

在上篇文章中,我們了解到,當(dāng)為某一個(gè)view添加約束時(shí),masonry的代碼執(zhí)行順序是下面這樣的。我們通過(guò)細(xì)致的分析了解到一條約束在被裝載到view之前,masonry都做了什么。其他三個(gè)約束的處理亦然。
self.translatesAutoresizingMaskIntoConstraints = NO;
MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
block(constraintMaker);

^(MASConstraintMaker *make) {
    make.left.mas_equalTo(lable.superview.mas_left).offset(10);
    make.right.mas_equalTo(-10);
    make.top.mas_equalTo(0);
    make.bottom.mas_equalTo(0);
}

return [constraintMaker install];
我們這篇文章主要講述,如何將存儲(chǔ)在MASConstraintMaker對(duì)象中的約束裝載到view上。在開(kāi)始之前,我們簡(jiǎn)短的回顧一個(gè)約束的收集過(guò)程。
1,創(chuàng)建一個(gè)MASConstraintMaker類對(duì)象愛(ài)麗絲,她持有要添加約束view喬治,并且持有一個(gè)數(shù)組,用來(lái)收集約束。
2,愛(ài)麗絲通過(guò).left創(chuàng)建一個(gè)MASViewConstraint類對(duì)象葛二蛋,葛二蛋持有了left約束條件,并被保存在愛(ài)麗絲的數(shù)組中。
3,葛二蛋通過(guò)mas_equalTo獲取到相對(duì)于父類的約束并存儲(chǔ)
4,葛二蛋通過(guò)offset獲取到子類與父類約束之間的改變值。
.right和.top和.bottom的處理情況與.left類似。
至此,葛二蛋兄弟4個(gè)持有了喬治所有的約束條件,而愛(ài)麗絲持有了喬治和葛二蛋兄弟4個(gè)。那接下來(lái)就是愛(ài)麗絲如何將二蛋四兄弟裝載到喬治身上,完成約束的添加任務(wù)。
好,我們開(kāi)始進(jìn)入正題:[constraintMaker install]。
 - (NSArray *)install {
    ///注意這里的self指代的是誰(shuí)。
    ///這個(gè)是干什么的,我們先不管,你只要知道這里if的代碼不會(huì)被執(zhí)行
    if (self.removeExisting) {
        NSArray *installedConstraints = [MASViewConstraint installedConstraintsForView:self.view];
        for (MASConstraint *constraint in installedConstraints) {
            [constraint uninstall];
        }
    }
    ///你不應(yīng)該還不知道這里的self是誰(shuí)。
    NSArray *constraints = self.constraints.copy;
    for (MASConstraint *constraint in constraints) {
        ///取出來(lái)的就是二蛋4兄弟之一
        constraint.updateExisting = self.updateExisting;
        ///調(diào)用了葛二蛋的裝載方法。
        [constraint install];
    }
    ///愛(ài)麗絲的數(shù)組被清空,但constraints仍然保存了一份二蛋4兄弟。這里你應(yīng)該知道copy的用法。體會(huì)這里作者為什么用copy處理一下數(shù)組。
    [self.constraints removeAllObjects];
    ///返回了二蛋4兄弟,注意,此時(shí)愛(ài)麗絲沒(méi)有再持有這四兄弟。
    return constraints;
}
不要著急,我們掰開(kāi)了一個(gè)一個(gè)看。
二蛋的裝載 [constraint install];
- (void)install {
    ///如果已經(jīng)被裝載,則不需要重復(fù)裝載
    if (self.hasBeenInstalled) {
        return;
    }
    這個(gè)我們先不管
    if ([self supportsActiveProperty] && self.layoutConstraint) {
        self.layoutConstraint.active = YES;
        [self.firstViewAttribute.view.mas_installedConstraints addObject:self];
        return;
    }

    MAS_VIEW *firstLayoutItem = self.firstViewAttribute.item;
    ///這個(gè)是要添加約束的view的自己的約束項(xiàng)
    NSLayoutAttribute firstLayoutAttribute = self.firstViewAttribute.layoutAttribute;
    MAS_VIEW *secondLayoutItem = self.secondViewAttribute.item;
    ///這個(gè)是相對(duì)于父視圖的約束項(xiàng)
    NSLayoutAttribute secondLayoutAttribute = self.secondViewAttribute.layoutAttribute;

    // alignment attributes must have a secondViewAttribute
    // therefore we assume that is refering to superview
    // eg make.left.equalTo(@10)
    ///這里作者的注釋已經(jīng)寫的很清楚了,如果你寫出了make.left.equalTo(@10)這樣的約束,就會(huì)用到這個(gè)處理,自動(dòng)獲取父類,并讓父類的對(duì)比約束和子類一樣。
    if (!self.firstViewAttribute.isSizeAttribute && !self.secondViewAttribute) {
        ///父類
        secondLayoutItem = self.firstViewAttribute.view.superview;
        ///父類的約束條件取子類的約束條件
        secondLayoutAttribute = firstLayoutAttribute;
    }
    ///好,接下來(lái)的代碼就是核心中的核心了。調(diào)用系統(tǒng)的autolayout進(jìn)行約束處理。MASLayoutConstraint繼承自NSLayoutConstraint。擴(kuò)展了一個(gè)有意思的key,你能體會(huì)到這個(gè)key的用處嗎?如果你不數(shù)熟悉autolayout的API,記得了解一下,這里不做過(guò)多解釋。你可以不用,但你最好知道。
    MASLayoutConstraint *layoutConstraint
    = [MASLayoutConstraint constraintWithItem:firstLayoutItem
                                    attribute:firstLayoutAttribute
                                    relatedBy:self.layoutRelation
                                       toItem:secondLayoutItem
                                    attribute:secondLayoutAttribute
                                   multiplier:self.layoutMultiplier
                                     constant:self.layoutConstant];
    ///其實(shí)看到這里,你就應(yīng)該思索,masonry的功能,不僅僅是添加普通約束。
    layoutConstraint.priority = self.layoutPriority;
    layoutConstraint.mas_key = self.mas_key;
    ///這個(gè)是干什么的?
    if (self.secondViewAttribute.view) {
        MAS_VIEW *closestCommonSuperview =       [self.firstViewAttribute.view mas_closestCommonSuperview:self.secondViewAttribute.view];
    NSAssert(closestCommonSuperview,
             @"couldn't find a common superview for %@ and %@",
             self.firstViewAttribute.view, self.secondViewAttribute.view);
        ///關(guān)鍵理解這個(gè)。這里還是要說(shuō),你真的需要理解一下autolayout是如何進(jìn)行布局的。公共父類進(jìn)行布局約束。
        self.installedView = closestCommonSuperview;
    } else if (self.firstViewAttribute.isSizeAttribute) {
        /**///了解了這個(gè),就好理解這里的判斷了。
            - (BOOL)isSizeAttribute {
                    return self.layoutAttribute == NSLayoutAttributeWidth
    || self.layoutAttribute == NSLayoutAttributeHeight;
            }
        */
        self.installedView = self.firstViewAttribute.view;
    } else {
        ///view相對(duì)于view.superView進(jìn)行布局
        self.installedView = self.firstViewAttribute.view.superview;
    }


    MASLayoutConstraint *existingConstraint = nil;
    ///更新或新增約束
    if (self.updateExisting) {
        existingConstraint = [self layoutConstraintSimilarTo:layoutConstraint];
    }
    if (existingConstraint) {
        // just update the constant
        existingConstraint.constant = layoutConstraint.constant;
        self.layoutConstraint = existingConstraint;
    } else {
        [self.installedView addConstraint:layoutConstraint];
        self.layoutConstraint = layoutConstraint;
        [firstLayoutItem.mas_installedConstraints addObject:self];
    }
}
到這里,整個(gè)裝載過(guò)程就完成了。但我相信,你還沒(méi)有很好的理解整個(gè)裝載過(guò)程。不要心急。這個(gè)過(guò)程只是引導(dǎo)大家對(duì)masonry做常用最簡(jiǎn)單的一個(gè)約束過(guò)程有一個(gè)大致的了解。接下來(lái),我將以這次裝載過(guò)程為線索,詳細(xì)的去理一理這個(gè)框架的脈絡(luò)和文件,對(duì)源碼進(jìn)行逐行的分析。我相信,有了前面這個(gè)簡(jiǎn)單的了解,我們對(duì)于后面的理解會(huì)容易得多。
最后編輯于
?著作權(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)容

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