Block (二) 塊方法的應用症狀枚舉

個人理解 OO是個什麼東西?大致都是經過這樣的過程 從高到低,

1. 先把最上層的東西拿來用了,理解了抽象概念之間的關係,也就是說先學會使用

2. 然而掌握內裏要理,可以使得在使用抽象方法的時候 更加得心應手

3. block 就是一個設計好的語法, 本文羅列了在實際代碼編寫中常見的 block ‘症狀’。


註釋:代碼中羅列了個人對一概念,是爲了幫助理解分析這些‘症狀’,沒有直指核心,只爲了從抽象————》細節的一個熟悉過程。




#import "MyObjc.h"


@interface MyObjc ()

@property (nonatomic, strong)void(^PropertyBlockA)(id something);


@end


@implementation MyObjc


void (^GlobalBlockA)(id something);


- (void)blockCaseExcute{


//    一、關於block對象和一般NSObject對象間的 持有關係(引用關係)循環引用問題的症狀


    //Case_01(reference) 直接聲明一個全局block,不是對象的屬性成員,塊中直接使用self無問題

    GlobalBlockA = ^(id something) {

        NSLog(@"something is:%@ | %@",something,self);

    };


    //Case_02(reference) 使用與當前對象存在持有關係的成員block,塊中直接使用self有警告提示

    //Xcode警告提示:Capturing‘self’strongly in this block is likely to lead to a retain cycle

    _PropertyBlockA = ^(id something) {

        NSLog(@"something is:%@ | %@",something,self);

    };

/*

    有幾個概念

 1.其實block也是一個對象快,存在自己的isa結構。

 2. block pointer的實體在methodfunction結束後就會被清掉

 3.蘋果設計,block 同樣遵循引用計數機制,

 PropertyBlockA 已經是MyObjc所持有的屬性成員變量,在上面的代碼塊中PropertyBlockA又引用持有自身的MyObjc對象(self),不難理解它們相互持有導致一個retain cycle了吧。

 */



//  二、 關於block 對塊區 變量進行修改的 __block修飾症狀

    //Case_03(variable change) 直接使用block塊,對外部的變量值進行修改,編譯器會給出報錯

    //Xcode 報錯提示:Variable is not assignablemissing __block type specifier

    NSString *strValue = @"originString";

    void(^VarBlockA)() = ^{

//        strValue = @"newString";

    };


    //Case_04(__book variable) 使用block塊,對__block 修飾的變量進行修改,可執行正常

    __block NSString *strOrigin = @"oldString";

    void (^VarBlockB)() = ^{

        strOrigin = @"newString";

    };

    VarBlockB();

/*

    有幾個概念

 4.block 塊默認對統一區塊(scope)變量的引用是做了一個const副本的拷貝處理的,也就會說 Case_03這種情況下,塊中strValue和外部聲明strValue已經不是一回事兒了

 5.蘋果設計,爲了避免編者Case_03的情況,乾脆禁止塊內對塊外變量進行直接修改,所以直接讓Xcode給出報錯提示。但是爲了解決該問題引入了__block字段

 6.__block 聲明的棧變量的引用被複制到了堆裏,複製之後棧上的以及產生的堆上的 block 都會引用這個堆上的變量。也就是說它保證了塊內外引用一致

 */





//  三、關於block 對塊區 變量進行處理時候, 數值變量和指針對象的不同症狀


    //Case_05(nomal variable) 輸出打印結果是200 而不是300

    int autoVarA = 100;

    void (^VarBlockC)() = ^ {

        NSLog(@"%d",autoVarA + 100);

    };

    autoVarA = 200;

    VarBlockC();


    //Case_06(pointer variable) 輸出打印結果是56789,而不是0123456789.

    NSMutableString *muString = [NSMutableString stringWithString:@"0123456789"];

    void (^VarBlockD)() = ^ {

        [muString deleteCharactersInRange:NSMakeRange(0, 5)];

        NSLog(@"%@",muString);

//        muString = [NSMutableString stringWithString:@"098765421"];

    };

    VarBlockD();



/*

    有幾個概念

 7.Case_05 的情況這個可以看出,對變量 const 副本的處理實在塊代碼主體部分實現的,先於塊代碼的實際調用時機。

 8.Case_06 (要注意的是 47概念強調的是變量值),如果這個變量的值是一個指針的位置,即這個變量是pointer的話,它指到的值是可以在block裏被改變的(遵循__block的是pointer本身). 

 */




//  四、 關於block 在遇見static 關鍵字時候的  應對處理症狀

    //Case_07(static variable) 輸出打印結果是200 ,而不是100

    static int autoValueB = 100;

    void (^VarBlockEOne)() = ^{

        NSLog(@"%d",autoValueB);

    };

    autoValueB = 200;

    VarBlockEOne();


    //Case_08(static variable) 輸出打印結果是300 並且不需要__block關鍵字就能在塊區對autoValueB進行修改

    void (^VarBlockETwo)() = ^{

        autoValueB = 300;

        NSLog(@"%d",autoValueB);

    };

    VarBlockETwo();


/*

    有幾個概念

 9. static 本身的特點,修飾的變量地址是靜態存在,始終不變,任何地方對它的使用都會尋到同一塊存儲區(指針地址)

 10.因此Case_07的效果, Case_08可以推導出一個結論:static的優先級是很高的,block也要滿足了它的特徵

 */






    //附註  參考文檔

//http://wiki.jikexueyuan.com/project/objc-zen-book/communication-between-objects.html

//http://blog.csdn.net/tlb203/article/details/7653817

}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章