厚積薄發(fā)之從Masonry 源碼看Objective-C [開篇]

前言: 這個(gè)系列可能不會(huì)分析, Masonry如何如何好, 估計(jì)多在分析源碼寫法, 不清楚的語法, 用了什么知識(shí)點(diǎn), 可能是這樣, 寫成什么樣也不確定, Masonry 是一個(gè)關(guān)于iOS開發(fā)的布局框架, Masonry是對(duì)NSLayoutConstraint 的封裝, 你知道的NSLayoutConstraint這個(gè)家伙使用起來很麻煩的, 語法相當(dāng)?shù)膯? 所以Masonry 簡(jiǎn)化了這個(gè)家伙的使用方式, 同時(shí)Masonry有一個(gè)小兄弟, 也在成長中, 成長的也是不錯(cuò), 你可以在Masonry的家里找到這個(gè)家伙(SnapKit), 不同的是SnapKit 是使用Siwft 寫的, 如果你都知道, 就當(dāng)是我在湊字?jǐn)?shù)(來 qq群打我好啦 認(rèn)真臉), 今天就主要介紹一些Masonry 相關(guān)的干貨, 反正你知道我是學(xué)習(xí)記錄, 談不上分享的, 我一貫就是這個(gè)態(tài)度的[囧].
下面的這張圖, 簡(jiǎn)單介紹了Masonry的主要大部分類, 你說: 沒寫全? 對(duì)的. 我能說沒有地方畫讓我刪了嗎? 認(rèn)真.

可能會(huì)寫這樣幾篇
厚積薄發(fā)之從Masonry 源碼看Objective-C [開篇]
[厚積薄發(fā)之從Masonry 源碼看Objective-C [開篇 續(xù)]]
[厚積薄發(fā)之從Masonry 源碼看Objective-C [開篇 續(xù)續(xù)]
[厚積薄發(fā)之從Masonry 源碼看Objective-C [開篇 續(xù)續(xù)續(xù)]
[厚積薄發(fā)之從Masonry 源碼看Objective-C [終篇 - 有始有終 希望最后能夠完美]

功力有限寫什么樣, 算什么樣. 有點(diǎn)死豬不怕燙的意思. 逃跑~.

目錄

  • Objective-C可變參數(shù)
  • 內(nèi)聯(lián)函數(shù) inline
  • mas_equalTo這個(gè)宏的實(shí)現(xiàn)
簡(jiǎn)單介紹

可變參數(shù): 在開始之前, 我決定先看看這個(gè)小知識(shí), 當(dāng)然你了解C 語言對(duì)此并不陌生, 然而我不像你, 我已經(jīng)把以前學(xué)的知識(shí), 交還給我的teacher了. 你可能也忘記了來跟我一起復(fù)習(xí)一遍, 在C 語言中的解釋大致是這個(gè)樣子的, 可變參數(shù)的實(shí)現(xiàn)必然不能缺少VA_LIST,
VA_LIST 是在C語言中是這樣解釋的, 用來解決變參問題的一組宏靠胜,所在頭文件:#include <stdarg.h>,用于獲取不確定個(gè)數(shù)的參數(shù)
而在Objective-C中 同樣也有關(guān)于處理不確定參數(shù)個(gè)數(shù)的實(shí)現(xiàn)使用va_list相關(guān), 接下來通過一段簡(jiǎn)單的代碼進(jìn)行演示.

可變參數(shù)在OC中如何實(shí)現(xiàn)?

  • va_list定義一個(gè)va_list變量, 這個(gè)變量的是指向參數(shù)的指針
  • va_start使用宏 定義va_list變量
  • va_argva_arg返回可變的參數(shù)峻贮,va_arg的第二個(gè)參數(shù)是你要返回的參數(shù)的類型,如果函數(shù)有多個(gè)可變參數(shù)的,依次調(diào)用va_arg獲取各個(gè)參數(shù)
  • va_end用va_end宏結(jié)束可變參數(shù)的獲取
- (NSMutableArray *)vaListUsing:(NSString *)p1,...NS_REQUIRES_NIL_TERMINATION{
    NSMutableArray *array = [NSMutableArray array];
    // 第一個(gè)參數(shù)進(jìn)數(shù)組
    [array addObject:p1];
    // 定義一個(gè)va_list變量, 這個(gè)變量的是指向參數(shù)的指針
    va_list v;
    id vStr;
    // 使用宏定義va_list變量
    va_start(v, p1);
    // va_arg返回可變的參數(shù)结榄,va_arg的第二個(gè)參數(shù)是你要返回的參數(shù)的類型,如果函數(shù)有多個(gè)可變參數(shù)的溯职,依次調(diào)用va_arg獲取各個(gè)參數(shù)
    while ((vStr = va_arg(v, id))) {
        [array addObject:vStr];
    }
    // 用va_end宏結(jié)束可變參數(shù)的獲取
    va_end(v);
    return array;
}
NSMutableArray *array = [self vaListUsing:@"Cancel", @"Other",@"OK", nil];
NSLog(@"%@", array); 

這是獲取的打印結(jié)果, 以上就是我通過代碼的形式表現(xiàn)出來的, 你可以通過獲取的參數(shù)名, 參數(shù)個(gè)數(shù), 可進(jìn)行適當(dāng)?shù)腢I布局什么的.
2016-11-23 15:58:09.225 Masonry閱讀理解****[5338:1112595] (*
** Cancel,**
** Other,**
** OK**
)

以上是不是跑題了, 我的回答是 并沒有! 你也相信我不能在這瞎扯淡.
接下來看看Masonry中如何使用這個(gè)小知識(shí)的呢.

在MASUtilities中

先看下面這段源碼, 通過上面的介紹, 我覺的你可能有點(diǎn)能明白了, 稍后解釋代碼, 首先看看inline C和C++語言中inline用來聲明內(nèi)聯(lián)函數(shù)的, 我還是有些印象的 作用是是 用來替代C中表達(dá)式形式的宏定義的. 而在OC用也是有同樣的作用.

static inline id _MASBoxValue(const char *type, ...) {
    va_list v;
    va_start(v, type);
    id obj = nil;
    if (strcmp(type, @encode(id)) == 0) {
        id actual = va_arg(v, id);
        obj = actual;
    } else if (strcmp(type, @encode(CGPoint)) == 0) {
        CGPoint actual = (CGPoint)va_arg(v, CGPoint);
        obj = [NSValue value:&actual withObjCType:type];
    } else if (strcmp(type, @encode(CGSize)) == 0) {
        CGSize actual = (CGSize)va_arg(v, CGSize);
        obj = [NSValue value:&actual withObjCType:type];
    } else if (strcmp(type, @encode(MASEdgeInsets)) == 0) {
        MASEdgeInsets actual = (MASEdgeInsets)va_arg(v, MASEdgeInsets);
        obj = [NSValue value:&actual withObjCType:type];
    } else if (strcmp(type, @encode(double)) == 0) {
        double actual = (double)va_arg(v, double);
        obj = [NSNumber numberWithDouble:actual];
    } else if (strcmp(type, @encode(float)) == 0) {
        float actual = (float)va_arg(v, double);
        obj = [NSNumber numberWithFloat:actual];
    } else if (strcmp(type, @encode(int)) == 0) {
        int actual = (int)va_arg(v, int);
        obj = [NSNumber numberWithInt:actual];
    } else if (strcmp(type, @encode(long)) == 0) {
        long actual = (long)va_arg(v, long);
        obj = [NSNumber numberWithLong:actual];
    } else if (strcmp(type, @encode(long long)) == 0) {
        long long actual = (long long)va_arg(v, long long);
        obj = [NSNumber numberWithLongLong:actual];
    } else if (strcmp(type, @encode(short)) == 0) {
        short actual = (short)va_arg(v, int);
        obj = [NSNumber numberWithShort:actual];
    } else if (strcmp(type, @encode(char)) == 0) {
        char actual = (char)va_arg(v, int);
        obj = [NSNumber numberWithChar:actual];
    } else if (strcmp(type, @encode(bool)) == 0) {
        bool actual = (bool)va_arg(v, int);
        obj = [NSNumber numberWithBool:actual];
    } else if (strcmp(type, @encode(unsigned char)) == 0) {
        unsigned char actual = (unsigned char)va_arg(v, unsigned int);
        obj = [NSNumber numberWithUnsignedChar:actual];
    } else if (strcmp(type, @encode(unsigned int)) == 0) {
        unsigned int actual = (unsigned int)va_arg(v, unsigned int);
        obj = [NSNumber numberWithUnsignedInt:actual];
    } else if (strcmp(type, @encode(unsigned long)) == 0) {
        unsigned long actual = (unsigned long)va_arg(v, unsigned long);
        obj = [NSNumber numberWithUnsignedLong:actual];
    } else if (strcmp(type, @encode(unsigned long long)) == 0) {
        unsigned long long actual = (unsigned long long)va_arg(v, unsigned long long);
        obj = [NSNumber numberWithUnsignedLongLong:actual];
    } else if (strcmp(type, @encode(unsigned short)) == 0) {
        unsigned short actual = (unsigned short)va_arg(v, unsigned int);
        obj = [NSNumber numberWithUnsignedShort:actual];
    }
    va_end(v);
    return obj;
}

#define MASBoxValue(value) _MASBoxValue(@encode(__typeof__((value))), (value))

由源代碼引申之內(nèi)聯(lián)函數(shù)

定義: 內(nèi)聯(lián)函數(shù)是指用inline關(guān)鍵字修飾的函數(shù)
作用: 去掉函數(shù)調(diào)用帶來的開銷
這個(gè)說的可以 可以去看看
代碼示例
仿照Masonry的示例代碼, 我簡(jiǎn)單測(cè)試了一下, 準(zhǔn)確性有待考察, 不過粗略的看, 貌似內(nèi)聯(lián)函數(shù)效率高一點(diǎn), 你怎么看? 歡迎評(píng)論拍磚. 教我做人.

static inline

static inline int xtAdd(int x, int y){
    int res = x + y;
    return res;
}
#define RESXyAdd(x, y) xtAdd(x, y)
    NSDate *tmpStartData = [NSDate date];
    int res = RESXyAdd(2, 3);
    // 內(nèi)聯(lián)
    // 2016-11-24 14:06:13.816 Masonry解析[7209:1504811] >>>>>>>>>>cost time = 0.608981 ms
    // 2016-11-24 14:00:57.229 Masonry解析[6870:1496409] >>>>>>>>>>cost time = 0.648022 ms
    // 2016-11-24 14:01:38.670 Masonry解析[6898:1497238] >>>>>>>>>>cost time = 0.645995 ms
    // 非內(nèi)聯(lián)
    // 2016-11-24 14:03:57.975 Masonry解析[7052:1500940] >>>>>>>>>>cost time = 0.657976 ms
    // 2016-11-24 14:04:57.955 Masonry解析[7101:1502351] >>>>>>>>>>cost time = 0.651002 ms
    NSLog(@"res === %d", res);
    double deltaTime = [[NSDate date] timeIntervalSinceDate:tmpStartData];
    NSLog(@">>>>>>>>>>cost time = %f ms", deltaTime * 1000);

接下來通過Masonry的使用來解釋上面提到的代碼
首先我定義了一個(gè)View 距上左88 寬高88 我分別可以使用make.width.height.mas_equalTo(88) make.width.height.mas_equalTo(@88) 或者 make.size.mas_equalTo(CGSizeMake(88, 88)) 通過這個(gè)宏我分別可以實(shí)現(xiàn)相應(yīng)很多操作. 其實(shí)這些都是通過上面提到的內(nèi)聯(lián)函數(shù)實(shí)現(xiàn)的. 先通過strcmp這個(gè)庫函數(shù)比較傳進(jìn)來的類型跟什么類型匹配, 之后放回相應(yīng)的對(duì)象. 完成對(duì)象的校驗(yàn). 這樣的效率很高, 同時(shí)使用方便.

    UIView *view = [UIView new];
    [self.view addSubview:view];
    view.backgroundColor = [UIColor redColor];
    [view mas_makeConstraints:^(MASConstraintMaker *make) {
        //
        make.top.equalTo(self.view.mas_top).with.offset(88);
        make.left.equalTo(self.view.mas_left).with.offset(88);
        // 我通過這個(gè)宏 傳遞88給width 和 height
        make.width.height.mas_equalTo(88);
        // 或者 @88 
        // make.width.height.mas_equalTo(@88);
        // 最終都是通過上述的內(nèi)聯(lián)函數(shù)實(shí)現(xiàn)了相應(yīng)的類型對(duì)應(yīng)
        // make.size.mas_equalTo(CGSizeMake(88, 88));
    }];

#define mas_equalTo(...) equalTo(MASBoxValue((VA_ARGS)))
mas_equalTo是個(gè)上面這樣表示的宏定義
#define MASBoxValue(value) _MASBoxValue(@encode(typeof((value))), (value))

而 MASBoxValue 最終是上面這個(gè)宏定義, 而最終 _MASBoxValue就是最上面提到的一大坨代碼(那個(gè)內(nèi)聯(lián)函數(shù)). 而不確定參數(shù), 我通過文章的開頭, 也進(jìn)行了交代.

總結(jié): 這個(gè)MASUtilities 文件 , 剩下就是一些重命名, 和宏定義的一些東西了, 這篇就到這, 篇幅太長是沒有耐心看下去的, 起個(gè)拋磚引玉的作用, 先這樣, 下一篇 還不知道怎么寫, 盡力寫的全面一點(diǎn), 讓自己有所收獲.

文/ 夏天然后

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末但两,一起剝皮案震驚了整個(gè)濱河市舆声,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌渔嚷,老刑警劉巖进鸠,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異形病,居然都是意外死亡客年,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門漠吻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來量瓜,“玉大人,你說我怎么就攤上這事侥猩±浦粒” “怎么了?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵欺劳,是天一觀的道長唧取。 經(jīng)常有香客問我,道長划提,這世上最難降的妖魔是什么枫弟? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮鹏往,結(jié)果婚禮上淡诗,老公的妹妹穿的比我還像新娘。我一直安慰自己伊履,他們只是感情好韩容,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著唐瀑,像睡著了一般群凶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上哄辣,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天请梢,我揣著相機(jī)與錄音赠尾,去河邊找鬼。 笑死毅弧,一個(gè)胖子當(dāng)著我的面吹牛气嫁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播够坐,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼寸宵,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了咆霜?” 一聲冷哼從身側(cè)響起邓馒,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤嘶朱,失蹤者是張志新(化名)和其女友劉穎蛾坯,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體疏遏,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡脉课,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了财异。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片倘零。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖戳寸,靈堂內(nèi)的尸體忽然破棺而出呈驶,到底是詐尸還是另有隱情,我是刑警寧澤疫鹊,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布袖瞻,位于F島的核電站,受9級(jí)特大地震影響拆吆,放射性物質(zhì)發(fā)生泄漏聋迎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一枣耀、第九天 我趴在偏房一處隱蔽的房頂上張望霉晕。 院中可真熱鬧,春花似錦捞奕、人聲如沸牺堰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伟葫。三九已至,卻和暖如春谷浅,著一層夾襖步出監(jiān)牢的瞬間扒俯,已是汗流浹背奶卓。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留撼玄,地道東北人夺姑。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像掌猛,于是被迫代替她去往敵國和親盏浙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

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