Block 和變量

X.4.1 變數(shù)的型態(tài)

我們可以在block中遇到平常在函數(shù)中會(huì)遇到的變數(shù)類型:

l 全域(global)變數(shù)或是靜態(tài)的區(qū)域變數(shù)(static local)。

l 全域的函數(shù)。

l 區(qū)域變數(shù)和由封閉領(lǐng)域(enclosing scope)傳入的參數(shù)。

除了上述之外block額外支援了另外兩種變數(shù):

在函數(shù)內(nèi)可以使用__block 變數(shù),這些變數(shù)在block中是可被修改的。

匯入常數(shù)(const imports)。

此外,在方法的實(shí)作里,block可以使用Objective-C的實(shí)體變數(shù)(instance variable)。

下列的規(guī)則可以套用到在block中變數(shù)的使用:

可以存取全域變數(shù)和在同一領(lǐng)域(enclosing lexical scope)中的靜態(tài)變數(shù)。

可以存取傳入block的參數(shù)(使用方式和傳入函數(shù)的參數(shù)相同)。

在同一領(lǐng)域的區(qū)域變數(shù)在block中將視為常數(shù)(const)。

可以存取在同一領(lǐng)域中以__block 為修飾詞的變數(shù)。

在block中宣告的區(qū)域變數(shù),使用方式和平常函數(shù)使用區(qū)域變數(shù)的方式相同。

下面的例子介紹了區(qū)域變數(shù)(上述第三點(diǎn))的使用方式:

1:intx = 123 ;

2:void(^printXAndY)(int) = ^(inty)

3:{

4:printf ("%d %d\n", x, y);

5:};

6:// 將會(huì)印出123 456

7:printXAndY( 456 );

8:就如上面第三點(diǎn)所提到的,在上例中的int x = 123的變量x,在傳入block后將視同常數(shù),因此若我們?cè)赽lock中試著去修改x的值時(shí)就會(huì)產(chǎn)生錯(cuò)誤,下面的例子將會(huì)無法通過編譯:

9:

10:intx = 123 ;

11:void(^printXAndY)(int) = ^(inty)

12:{

13:// 下面這一行是錯(cuò)的,因?yàn)閤 在這是一個(gè)常數(shù)不能被修改。

14:x = x + y;

15:printf ("%d %d\n", x, y);

16:};

若在block中想要修改上面的變數(shù)x,必須將x宣告加上修飾詞__block,請(qǐng)參考接下來這一小節(jié)的介紹。

X.4.2 __block 型態(tài)變數(shù)

我們可以藉由將一個(gè)由外部匯入block的變數(shù)放上修飾詞__block來讓這個(gè)變數(shù)由唯讀變成可以讀和寫,不過有一個(gè)限制就是傳入的變數(shù)在記憶體中必須是一個(gè)占有固定長(zhǎng)度記憶體的變數(shù),__block修飾詞無法使用于像是變動(dòng)長(zhǎng)度的陣列這類不定長(zhǎng)度的變數(shù),請(qǐng)參考下面的范例:

1:// 加上__block 修飾詞,所以可以在block 中被修改。

2:__blockintx = 123 ;

3:void(^printXAndY)(int) = ^(inty)

4:{

5:x = x + y;

6:printf ("%d %d\n", x, y);

7:};

8:// 將會(huì)印出579 456

9:printXAndY( 456 );

10://x 將會(huì)變成 579;

11:下面我們使用一個(gè)范例來介紹各類型的變數(shù)和block之間的互動(dòng):

12:

13:externNSInteger CounterGlobal;

14:staticNSInteger CounterStatic;

15:{

16:NSInteger localCounter = 42 ;

17:__blockcharlocalCharacter;

18:void(^aBlock)(void) = ^(void)

19:{

20:++ CounterGlobal ;//可以存取。

21:++ CounterStatic ;//可以存取。

22:CounterGlobal = localCounter;//localCounter在block 建立時(shí)就不可變了。

23:localCharacter ='a';//設(shè)定外面定義的localCharacter 變數(shù)。

24:};

25:++localCounter;//不會(huì)影響的block 中的值。

26:localCharacter ='b';

27:aBlock();//執(zhí)行block 的內(nèi)容。

28://執(zhí)行完后,localCharachter 會(huì)變成'a'

29:}

X.4.3 物件和Block變數(shù)

Block

支援在Objective-C、C++物件和其他block中當(dāng)作變數(shù)來使用,不過因?yàn)樵诖蟛糠值那闆r我們都是使用Objective-C的撰寫程式,因此在這一小節(jié)我們僅針對(duì)Objective-C的情況進(jìn)行介紹,至于其他兩種情況就留給有興趣的讀者再自行深入研究了。

x.4.3.1 Objective-C 物件

在擁有參考計(jì)數(shù)(reference-counted)的環(huán)境中,若我們?cè)赽lock中參考到Objective-C的物件,在一般的情況下它將會(huì)自動(dòng)增加物件的參考計(jì)數(shù),不過若以__block為修飾詞的物件,參考計(jì)數(shù)則是不受影響。

如果我們?cè)贠bjective-C的方法中使用block時(shí),以下幾個(gè)和記憶體管理的事是需要額外注意的:

l 若直接存取實(shí)體變數(shù)(instance variable),self的參考計(jì)數(shù)將被加1。

l 若透過變數(shù)存取實(shí)體變數(shù)的值,則只變數(shù)的參考計(jì)數(shù)將被加1。

以下程式碼說明上面兩種情況,在這個(gè)假設(shè)instanceVariable是實(shí)體變數(shù):

1:dispatch_async (queue, ^{

2:// 因?yàn)橹苯哟嫒?shí)體變數(shù)instanceVariable ,所以self 的retain count 會(huì)加1

3:doSomethingWithObject (instanceVariable);

4:});

5:id localVaribale = instanceVariable;

6:dispatch_async (queue, ^{

7://localVariable 是存取值,所以這時(shí)只有l(wèi)ocalVariable 的retain count 加1

8://self 的 return count  并不會(huì)增加。

9:doSomethingWithObject (localVaribale);

10:});

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • Block是iOS在4.0之后新增的程式語法,嚴(yán)格來說block的概念并不算是基礎(chǔ)程式設(shè)計(jì)的范圍,對(duì)初學(xué)者來說也不...
    Bager閱讀 935評(píng)論 0 0
  • Block是iOS在4.0之后新增的語法,在iOS SDK 4.0之后,block幾乎出現(xiàn)在所有新版的API之中,...
    阿窩額咦嗚芋閱讀 480評(píng)論 0 0
  • **Block **是iOS在4.0之后新增的語法,在iOS SDK 4.0之后,block幾乎出現(xiàn)在所有新版的A...
    ios_geek閱讀 796評(píng)論 0 0
  • 前言 Blocks是C語言的擴(kuò)充功能,而Apple 在OS X Snow Leopard 和 iOS 4中引入了這...
    小人不才閱讀 3,787評(píng)論 0 23
  • 2.1 Blcoks概要 2.1.1 什么是Blocks Blocks是C語言的擴(kuò)充功能——“帶有自動(dòng)變量(即局部...
    SkyMing一C閱讀 2,396評(píng)論 6 18