Block (二) 块方法的应用症状枚举

来源:互联网 发布:零售药店收银软件 编辑:程序博客网 时间:2024/05/16 18:12

个人理解 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修饰的变量进行修改,可执行正常

    __blockNSString *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 = [NSMutableStringstringWithString:@"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

    staticint 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

}


0 0
原创粉丝点击