iOS利用block實(shí)現(xiàn)鏈?zhǔn)骄幊谭椒?/h2>

【一】遭遇

到今天iOS開發(fā)中最常用的語言還是objc,市場(chǎng)就像泰坦尼克號(hào),人雖然在上樓,但是船在下沉,所以人還是在下沉。雖然swift出現(xiàn)的迅猛,但是大部分開發(fā)者面對(duì)的還是objc。什么時(shí)候swift替代objc,今天的objc開發(fā)人員也不用太著急,說不定船都沉了(蘋果保佑)。

objc最令人頭疼的是他看起來像部落語言一樣的表達(dá)。比如下面這行新手代碼,但是就像求偶訊號(hào)一樣晦澀:

[[NSMutableDictionary alloc] initWithContentsOfURL:[NSURL URLWithString:@"a.txt"]][@"persons"][12];

但它并沒有告訴別人任何有意義的事情,分解一下語法就像下面一樣:

NSMutableDictionary* dict = [[NSMutableDictionary alloc] initWithContentsOfURL:[NSURL URLWithString:@"a.txt"]];

NSArray* arr = dict[@"persons"];

arr[12];

語言發(fā)展到今天,代碼的普世價(jià)值不是效率,而是開發(fā)效率。這就是為什么java能夠成為王者的原因。因?yàn)閖ava寫起來快,好讀。

【二】探索

objc比起java又慢又不好讀。那么如何讓objc看起來像java一樣呢。縱觀objc全部語法,只有block能夠辦到。我們來看block的定義

returnType? (^name)? (val1, val2, ...);

返回類型? ? 變量名? ? ? ? 參數(shù)列表//我們可以從表面認(rèn)為他是一根指向函數(shù)的指針,這個(gè)函數(shù)的樣子如下(returnType)name(val1, val2, ...)

{//......}

block具有一個(gè)函數(shù)的外觀,又被當(dāng)作一個(gè)變量。那么block就具備兩個(gè)功能,第一:可以作為類的屬性被'點(diǎn)'出來。第二:可以當(dāng)作函數(shù)直接調(diào)用。下面逐個(gè)解釋,第一個(gè)類的屬性可以點(diǎn)出來,比如person.name;這很好理解,你一定見過,str.length;對(duì)吧。第二個(gè)呢,block作為一個(gè)變量,但是又可以把它當(dāng)作指向函數(shù)的指針一樣調(diào)用。

NSString*(^myBlock)() = ^(){return@"菊樂"; };//定義一個(gè)返回值為NSString類型,無參的,并且名字叫做myBlock的blockmyBlock();//這一行就是調(diào)用NSString result= myBlock();//這是取出block執(zhí)行后拿到的返回值,也就是@"菊樂"

這里再解釋一次block的定義:上面的myBlock可以認(rèn)為是指向一個(gè)定義如下的函數(shù)的指針,這個(gè)函數(shù)是

(NSString*) myBlock()

{//...}//指向函數(shù)的指針NSString* (*p) ();//可以認(rèn)為指針p就是myBlock(其實(shí)block的真實(shí)身份更加復(fù)雜)

【三】推理

我們來幻想一下objc寫起來是這樣的

//設(shè)置視圖位置和大小,設(shè)置視圖背景色view.setFrame(0,0,50,50).setBackgroundColor(@"#0c0c0c".toColor() );//移除空格并在控制臺(tái)打印字詩句@"白 日 依 山 盡 , 黃 河 入 海 流".removeStr(@"").nslog();

而實(shí)際上要寫5行的代碼,一行3秒,3行15秒。就這樣錯(cuò)過了一次搖一搖的機(jī)會(huì),人生在緩慢的艱難,而我們卻還一無所知。

view.frame = CGRectMake(0,0,50,50);

view.backgroundColor= [UIColor colorWithRed:0.5green:0.5blue:0.5alpha:1.0];

NSString* str=@"白 日 依 山 盡 , 黃 河 入 海 流";

str= [str stringByReplacingCharactersInRange:@""withString:@""];

NSLog(str);

現(xiàn)在我們來倒著分析如何使用block來實(shí)現(xiàn)鏈?zhǔn)骄幊?,再來觀察這句話:

view.setFrame(0,0,50,50).setBackgroundColor(@"#0c0c0c".toColor() );

其中的setFrame和setBackgroundColor他們是什么?大家一定知道是屬性??墒菍傩允遣粠Юㄌ?hào)的,setFrame()他是屬性嗎?那他又是什么呢?setFrame()是屬性,并且是block類型的,因?yàn)閎lock可以加括號(hào)調(diào)用。就像這樣調(diào)用block();那么還有一個(gè)問題很關(guān)鍵:view.setFrame().setBackgroundColor();怎么可以連續(xù)點(diǎn)出來,這剛開始很不好理解。這并不難,我們往前看那句話:

NSString result = myBlock();

細(xì)心的去發(fā)現(xiàn),block是可以有返回值的,那么我們就依靠這個(gè)返回值就可以點(diǎn)出一堆屬性,一直點(diǎn)下去,這樣我們的鏈?zhǔn)骄幊痰乃悸肪屯恕?/p>

【四】實(shí)踐

我們現(xiàn)在就來實(shí)現(xiàn)view.setFrame().setBackgroundColor();

首先準(zhǔn)備一個(gè)分類。頭文件定義如下:

//UIView+Extension.h#import@interfaceUIView(Extesion)@PRoperty (nonatomic,copy) UIView* (^setFrame)(CGFloat x, CGFloat y, CGFloat w, CGFloat h);

@property (nonatomic,copy) UIView* (^setBackgroundColor)(UIColor*color);@end

我們?cè)赨IView類上擴(kuò)展了兩個(gè)額外屬性setFrame和setBackgroundColor,這意味著只要是繼承自UIView的對(duì)象就可以點(diǎn)出來這兩個(gè)屬性。

現(xiàn)在我們需要理解一下兩個(gè)的區(qū)別:

view.setFrame;//這是獲取屬性,它返回一個(gè)blockview.setFrame();//這是獲取屬性,它返回一個(gè)block,最后我們使用括號(hào)調(diào)用了這個(gè)block,這個(gè)block的返回值是UIView類型的對(duì)象,那么他就可以繼續(xù)點(diǎn)出下一個(gè)屬性了

view.setFrame()這句話的末尾因?yàn)榧由狭死ㄌ?hào)所以執(zhí)行了block,而他的返回類型是一個(gè)UIView對(duì)象,所以可以調(diào)用setBackgroundColor();

這里解釋一下為什么用copy,block這種類型本來是值類型的,他本來是在棧上的,在ARC環(huán)境下如果被任何強(qiáng)指針過了一次,編譯器就會(huì)把他進(jìn)行一次copy,放到堆內(nèi)存中。block的retain行為默認(rèn)是用copy的行為實(shí)現(xiàn)的,因?yàn)閎lock變量默認(rèn)是聲明為棧變量的,為了能夠在block的聲明域外使用應(yīng)該使用copy。

接下來實(shí)現(xiàn).m文件內(nèi)的代碼:

- (UIView *(^)(CGFloat, CGFloat, CGFloat, CGFloat))setFrame

{return?;

}

不難分析出,這個(gè)屬性的類型是block,具體是UIView* (^)(CGFloat , CGFloat , CGFloat , CGFloat )類型。那么‘?’就是這樣一個(gè)類型的對(duì)象??墒沁@個(gè)對(duì)象從哪里獲得呢,如果是個(gè)NSString我還存儲(chǔ)的有,而這個(gè)對(duì)象只能無從獲取。這并不重要,因?yàn)槲覀儾⒉灰猙lock對(duì)象本身,我們需要的是:block對(duì)象他能夠執(zhí)行一些功能就夠了。所以屬性內(nèi)部返回一個(gè)臨時(shí)block對(duì)象,這個(gè)block內(nèi)部呢去執(zhí)行一些功能,最重要的是block內(nèi)部一定要返回UIView類型的對(duì)象。編譯器會(huì)對(duì)block的類型進(jìn)行苛刻的檢測(cè)。

- (UIView *(^)(CGFloat, CGFloat, CGFloat, CGFloat))setFrame

{return^(CGFloat x, CGFloat y, CGFloat w, CGFloat h){//返回臨時(shí)變量的block

self.frame=CGRectMake(x, y, w, h);//block執(zhí)行一些功能returnself;//block執(zhí)行完畢的返回值

};

}

下面是.m文件的實(shí)現(xiàn)

//UIView+Extension.m#import"UIView+Extension.h"@implementationUIView(Extesion)- (UIView *(^)(CGFloat, CGFloat, CGFloat, CGFloat))setFrame

{return^(CGFloat x, CGFloat y, CGFloat w, CGFloat h){

self.frame=CGRectMake(x, y, w, h);returnself;

};

}- (void)setSetFrame:(UIView *(^)(CGFloat, CGFloat, CGFloat, CGFloat))setFrame{};//該屬性不需要從外部設(shè)置,不想報(bào)警告就寫空方法- (UIView *(^)(UIColor *))setBackgroundColor

{return^(UIColor*color){

self.backgroundColor=color;returnself;

};

}- (void)setSetBackgroundColor:(UIView *(^)(UIColor *))setBackgroundColor{};@end

【五】崩潰

objc中向nil對(duì)象發(fā)送任何消息都不會(huì)崩潰,但是發(fā)送他不能處理的消息類型就會(huì)崩潰,這也是最經(jīng)常遇到了情況。還有這樣也會(huì)崩潰:nil.length; view.length;調(diào)用不存在的屬性也會(huì)崩潰。那么這是我們要處理的一個(gè)重要的情況。

試想,一行代碼中間突然有一個(gè)處理返回了nil給下一個(gè)環(huán)節(jié),一調(diào)用就崩潰,關(guān)鍵是斷點(diǎn)并不能明確告訴你在哪一行。我們只能從控制臺(tái)中獲得調(diào)試信息。這也是鏈?zhǔn)骄幊痰谋锥酥弧?/p>

【六】效率

關(guān)于效率,肯定比原生低那么一丁點(diǎn)的,幾乎可以忽略的,只是多了一次屬性調(diào)用,一次一臨時(shí)block的創(chuàng)建,一次block的執(zhí)行。博主的觀點(diǎn)是為了提高開發(fā)效率,而降低一些運(yùn)行效率。有時(shí)候也是值得的。最后蘋果也是大力提倡我們使用block的。祝愉快。

最后編輯于
?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 前言 Blocks是C語言的擴(kuò)充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了這...
    小人不才閱讀 3,884評(píng)論 0 23
  • iOS代碼塊Block 概述 代碼塊Block是蘋果在iOS4開始引入的對(duì)C語言的擴(kuò)展,用來實(shí)現(xiàn)匿名函數(shù)的特性,B...
    smile刺客閱讀 2,468評(píng)論 2 26
  • Block使用場(chǎng)景,可以在兩個(gè)界面的傳值,也可以對(duì)代碼封裝作為參數(shù)的傳遞等。用過GCD就知道Block的精妙之處。...
    Coder_JMicheal閱讀 832評(píng)論 2 1
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,098評(píng)論 0 9
  • 最近一段時(shí)間,都太過無聊,定好的看書,學(xué)習(xí),都被新認(rèn)識(shí)的朋友所打斷,也許剛認(rèn)識(shí),都有一些新鮮感吧,彼此聊了很多,有...
    JING1211閱讀 178評(píng)論 0 1

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