Masonry和鏈?zhǔn)骄幊?/h1>

轉(zhuǎn)自
Objective-C 鏈?zhǔn)骄幊?br> 最近看到了鏈?zhǔn)骄幊毯秃瘮?shù)式編程這兩個概念代兵,網(wǎng)上查了一些資料,但是發(fā)現(xiàn)資料都千篇一律,我心中存在的這幾個疑惑根本沒有幫我解開颇玷。
1,為什么可以使用.語法來調(diào)用方法宠能,而不是使用OC里面的[ ]亚隙。
2,為什么方法里面明明沒有參數(shù)违崇,當(dāng)方法的返回值是一個block時阿弃,使用.語法調(diào)用方法可以傳參數(shù)。
不知道有沒有和我遇到一樣的問題的同學(xué)羞延,周末的時間用了一個下午一點一點琢磨渣淳。下面我來一一解釋這些問題。
首先伴箩,先簡紹下block

block的作用,主要用于回調(diào)傳值,解耦合
1.當(dāng)方法的參數(shù)是block類型,block的參數(shù)用于從內(nèi)向外傳值
2.block的返回值用于從外向內(nèi)返回結(jié)果

這兩句話是能實現(xiàn)鏈?zhǔn)骄幊痰年P(guān)鍵入愧,好好理解下。

對于block,我們可以這樣理解
舉個例子:大家想必都看過警匪片瞎领,在片子里面瓮增,壞蛋都喜歡安裝一些遙控的炸彈來威脅警察,如果警察不聽話旁赊,壞蛋就會引爆炸彈。這里的炸彈就可以理解為block椅野,而遙控器就可以理解為調(diào)用block终畅。block就是我們提前存儲的一段代碼塊,當(dāng)我們需要使用的時候才去調(diào)用它竟闪。下面來看一段網(wǎng)絡(luò)請求數(shù)據(jù)的代碼來理解下這個遙控炸彈离福。

@interface ReuuestData : NSObject

//定義無參數(shù)無返回值的block

  • (void)requestDataSucc:(void(^)())succBlock fail:(void(^)())failBlock;
    @end
    @implementation ReuuestData
  • (void)requestDataSucc:(void (^)())succBlock fail:(void (^)())failBlock {
    //這一塊就相當(dāng)于炸彈的遙控器, 在成功或者失敗里引爆炸彈
    if (/* DISABLES CODE */ (YES)) {
    succBlock(); //成功的block
    }else {
    failBlock(); //失敗的block
    }
    }
    @end
    下面我們在ViewController里使用下

ReuuestData *obj = [ReuuestData alloc] init];
//這一塊就相當(dāng)于埋了一個炸彈炼蛤, 我們不管他什么時候會爆炸妖爷,決定他爆炸的時刻是安裝了這個炸彈接收信號的遙控器
[obj requestDataSucc:^{
//成功的回調(diào)
} fail:^{
//失敗的回調(diào)
}];
因為我們在進(jìn)行網(wǎng)絡(luò)請求時不知道什么時候請求會成功, 我們首先讓obj 調(diào)用請求網(wǎng)絡(luò)的方法理朋, 此時赠涮,開始網(wǎng)絡(luò)請求子寓, 當(dāng)請求結(jié)束后,會走對應(yīng)的成功或者失敗的方法笋除。

接下來理解了上面的網(wǎng)絡(luò)請求的例子斜友,咱們就以一個例子來講解鏈?zhǔn)骄幊蹋@個例子在其他文章中也都有介紹垃它,為了保證文章的完整性鲜屏,我就再啰嗦一遍這個例子。
1国拇、首先創(chuàng)建一個Person類洛史,并為其增加兩個方法

  • (void)name1;

  • (void)sex1;
    2、實現(xiàn)方法

  • (void) name1 {
    NSLog(@"name");
    }

  • (void) sex1 {
    NSLog(@"sex")
    }
    3酱吝、實例化對象也殖,并調(diào)用方法

Person*person = [[Personalloc]init];
[person name1];
[person sex1];
以上三部很簡單,相比大家都能看的懂务热。而我們最終的目標(biāo)是

person.name(@"Jason").sex(@"男");
首先我們要實現(xiàn)

[[person name] sex];
實現(xiàn)這個目標(biāo)很簡單忆嗜,只需要調(diào)用[person name]的時候返回一個Person對象就可以了,下面我們來修改代碼

  • (Person *)name2;
    • (Person *)sex2;
  • (Person *)name2 {
    NSLog(@"name");
    return self;
    }
  • (Person *)sex2 {
    NSLog(@"sex");
    return self;
    }
    這樣就可以實現(xiàn)了崎岂,

[[person name2] sex2];
這離我們的最終目標(biāo)還有一段距離捆毫。
先拆分下目標(biāo),先實現(xiàn)

[[person name](@"Jason") sex](@"男"); //這個是不是和我們最終的目標(biāo)很像冲甘,只需把中括號換成(.)就可以了

person.name(@"Jason").sex(@"男");

我們都知道OC里面調(diào)用方法使用的是[obj func]绩卤,向一個方法發(fā)送一條消息。而沒有obj.func(param)的形式江醇,要想實現(xiàn)這個濒憋,我們自然而然的會想到OC里面的block,只有block才是以()的方式調(diào)用的陶夜。
1跋炕、我們可以返回一個block,然后使用()去掉用律适。
2、那么我們要如何實現(xiàn)連續(xù)調(diào)用呢遏插?我們再分析捂贿,要調(diào)用一個類的實例方法,必須由這個類的實例對象才能調(diào)用胳嘲,如[[person name] sex]; 我們之所以可以連續(xù)使用[ ]厂僧, 是因為我們返回了一個該實例對象。如果在返回的block里面返回一個實例對象不就可以連續(xù)調(diào)用了嗎了牛,而block正好也能返回一個對象颜屠。下面我們再改寫代碼辰妙。

//返回一個block,而block的返回值是一個Person對象

  • (Person * (^)())name3;
  • (Person * (^)())sex3;
  • (Person * (^)())name3 {
    //可以直接返回一個block
    return ^Person *(){
    return self;
    };
    }
  • (Person * (^)())sex3 {
    //也可以定義一個block甫窟,接收返回的block密浑,再把block返回
    //等號右邊的Person *()可以省略不寫,Person *省略不寫的原因是返回值本身可以不寫粗井,()可以省略不寫的原因是block無參數(shù)時可以省略()
    Person *(^block)() = ^Person *(){
    return self;
    };
    return block;
    }
    此時我們調(diào)用方法

person name3 sex3;
看到如此的寫法是不是很奇怪尔破, OC里面調(diào)用方法沒有這樣寫的呀,不要著急浇衬,我們一步一步分解懒构。

[person name3]
這一步大家都很熟悉吧,我們在前面講過耘擂,name3方法返回的是一個block胆剧,我們打印下這個返回值,看看到底是個什么鬼醉冤?

NSLog(@"%@", [person name3]);
//<NSMallocBlock: 0x7fa7714193c0>
打印結(jié)果告訴我們秩霍,返回值是一個block

//這種寫法就相當(dāng)于我們?nèi)フ{(diào)用了一個block,前面說過冤灾,只有block才會有()的這種語
//還記得前面講的定時炸彈嗎前域,當(dāng)執(zhí)行完[person name3]這句代碼的時候,我們就找到了那個炸彈韵吨,再執(zhí)行()的時候匿垄,我們就引爆了炸彈。
person name3
前面說過归粉,block也是有返回值的椿疗,我們同樣打印下block的返回值

NSLog(@"%@", person name3);
<Person: 0x7fd9e9daf980> //返回值是一個對象,很關(guān)鍵
接下來我們換一種寫法來理解這句代碼糠悼,把這句代碼分成兩步届榄。

//1.聲明一個返回值是Person類型, 無參數(shù)的block倔喂,用于接收返回值
Person * (^returnBlock)() = [person name3];
NSLog(@"%@", [person name3]); //<NSMallocBlock: 0x7f93bfc105a0>
NSLog(@"%@", returnBlock); //<NSMallocBlock: 0x7f93bfcb7a00>
//2.調(diào)用block
returnBlock(); //注意此處返回的是一個Person對象铝条, 這是我們實現(xiàn)鏈?zhǔn)骄幊痰年P(guān)鍵
NSLog(@"%@", returnBlock()); //<Person: 0x7fd9e9daf980>
上面的寫法是不是容易理解一點呢,首先聲明一個返回值是Person類型席噩, 無參數(shù)的block班缰,用于接收[person name3]的返回值, 此時我們找到了我們先前已經(jīng)存好的block(炸彈)悼枢,然后再去調(diào)用block(引爆炸彈)
下面我們再來看之前的代碼

[[person name3]() sex3]();

//這一步操作分解之后就是這四步埠忘, 此處也能看出,鏈?zhǔn)骄幊棠芴岣唛_發(fā)效率和提高代碼的可讀性
Person * (^returnNameBlock)() = [person name3];
Person *personName = returnNameBlock();
Person * (^returnSexBlock)() = [personName sex3];
Person *personSex = returnSexBlock();
此時離我們最終實現(xiàn)的效果的前一步還差一點,就是沒有參數(shù)莹妒,我們再改寫代碼名船,加上參數(shù),實現(xiàn)下面的效果

person name sex;
改寫

// 函數(shù)的返回值是一個Block旨怠,Block的返回值是當(dāng)前對象渠驼,Block有一個參數(shù)

  • (Person * (^)(NSString *name))name4; //設(shè)置參數(shù)
  • (Person * (^)(NSString *sex))sex4;
  • (Person * (^)(NSString *name))name4 {
    // 方法的返回是一個”有參有返回值的Block“
    return ^Person *(NSString *name){
    NSLog(@"%@", name);
    // block的返回值是當(dāng)前對象
    return self;
    };
    }
  • (Person * (^)(NSString *sex))sex4 {
    return ^Person *(NSString *sex) {
    NSLog(@"%@", sex);
    return self;
    };
    }
    //調(diào)用

//(@"Jason")這個參數(shù)是block的參數(shù),并且是block作為返回值的參數(shù)运吓,在文章的開頭已經(jīng)說過渴邦,block的返回值參數(shù)用于從外向內(nèi)返回結(jié)果,這就是為什么我們在外面?zhèn)魅雲(yún)?shù)(@"Jason")拘哨,而在函數(shù)內(nèi)部會打印我們傳入的參數(shù)谋梭,這點不要搞錯。-->>解釋文章開頭第二個問題
person name4 sex4;
OK倦青,經(jīng)歷九九八十一難瓮床,我們終于到達(dá)了天竺,離求取真經(jīng)只差一步了
我們要的結(jié)果是

person.name(@"Jason").sex(@"男");
而我們現(xiàn)在的結(jié)果和這個目標(biāo)只差一步了产镐,是不是感覺有點小激動呢隘庄。
還是文章開頭的第一個問題-->> 為什么可以使用.語法來調(diào)用方法,而不是使用OC里面的[ ]癣亚。
首先我們要知道OC里面的屬性聲明默認(rèn)是私有的丑掺,外部是不可以直接訪問的,而setter個getter方法是可以間接訪問屬性的述雾。其實在使用self.propert語法時街州,不是直接訪問屬性,而是隱士的調(diào)用了setter或者getter方法來訪問屬性的玻孟,在編譯與運行期間唆缴,并不關(guān)心你是否在真正的在獲取一個屬性。要實現(xiàn)使用.點語法調(diào)用方法黍翎,你的方法面徽,必須有一個返回值,并且無參數(shù)匣掸。這樣才符合getter方法的書寫規(guī)范趟紊,而我們最終使用的方法整好符合這種規(guī)范。所以碰酝,你就可以直接使用 person.name(@"Jason").sex(@"男");來調(diào)用方法了霎匈。

最終我們實現(xiàn)了

person.name(@"Jason").sex(@"男");
你可以盡情的 . 下去了

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者

  • 序言:七十年代末,一起剝皮案震驚了整個濱河市砰粹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖碱璃,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件弄痹,死亡現(xiàn)場離奇詭異,居然都是意外死亡嵌器,警方通過查閱死者的電腦和手機(jī)肛真,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爽航,“玉大人蚓让,你說我怎么就攤上這事〖フ洌” “怎么了历极?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長衷佃。 經(jīng)常有香客問我趟卸,道長,這世上最難降的妖魔是什么氏义? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任锄列,我火速辦了婚禮,結(jié)果婚禮上惯悠,老公的妹妹穿的比我還像新娘邻邮。我一直安慰自己,他們只是感情好克婶,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布筒严。 她就那樣靜靜地躺著,像睡著了一般鸠补。 火紅的嫁衣襯著肌膚如雪萝风。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天紫岩,我揣著相機(jī)與錄音规惰,去河邊找鬼。 笑死泉蝌,一個胖子當(dāng)著我的面吹牛歇万,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播勋陪,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼贪磺,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了诅愚?” 一聲冷哼從身側(cè)響起寒锚,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后刹前,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泳赋,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年喇喉,在試婚紗的時候發(fā)現(xiàn)自己被綠了祖今。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡拣技,死狀恐怖千诬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情膏斤,我是刑警寧澤徐绑,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站掸绞,受9級特大地震影響泵三,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜衔掸,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一烫幕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧敞映,春花似錦较曼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至冕末,卻和暖如春萍歉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背档桃。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工枪孩, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人藻肄。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓蔑舞,卻偏偏與公主長得像,于是被迫代替她去往敵國和親嘹屯。 傳聞我的和親對象是個殘疾皇子攻询,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

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