关于block(三)----变量引用 + __block修饰

block引用外部变量,是在block_impl_struct上创建新的变量,然后引用外部变量值或指针,但是block认为其内部引用的外部变量和外部变量是统一体,所以始终遵循一个原则(以下简称一致原则):
在进行改值操作时,必须使变量在block内外保持一致

当使用__block修饰的时候,就可以把引用的外部变量转变为结构体(在关于block(一)中有讲到),类似于OC的对象,block内引用结构体的指针,当改变外部变量时,只需要改变结构体内部成员变量的值就可以,结构体指针不会变,block内外变量结构体保持一致

代码1


    int notChange =77;

    void(^myBlock)(void) = ^() {
        printf("ss--%d\n",notChange);
    };

    myBlock();

上面的代码,notchange在block内外的地址不一样;

原因:myBlock的内部引用了notChange的值,而不是地址,相当于重新创建了个一个int内存,所以地址不一样。

代码2


    __block int h =9;   
    __block char *string = str;
    NSMutableString * string0 = [[NSMutableString alloc] initWithString:@"123"];

    void(^staBlock1)(void) = ^{
        h =13;
        string ="bbss";
        string0 = [NSMutableString stringWithString:@"1111"];
        [string0 appendString:@"456"];
        printf("%s\n",str);
    };

    staBlock1();

上面的代码:

1.基本类型h在block内改变值时,必须用__block,否则不被允许

原因:因为block内的h和block外的地址不一样,赋值就相当于在block内进行这样的操作:int local = h;local = 13;,h在block外部并没有变化,由于这里h要关联block内外,那么必须要使用__block,将外部基本类型变量转化为结构体,通过block引用结构体的指针来同时改变变量在block内部和外部的值

一致原则:因为h在block内外地址不一样,所以对block内部的变量直接赋值就违背了一致原则,导致变量内外不一致;

2.字符串的赋值,也必须要使用__block

原因:虽然这里block引用的是string的指针,这时候用指针进行赋值string = "bbss";,那么就是让string指向字符串的首地址,在改变指针的指向,不符合一致原则

3.OC对象NSMutableString修改,直接引用就可以

原因:其实OC对象进行直接赋值也是不被允许的string0 = [NSMutableString stringWithString:@"1111”];;从这里可以看出,在block内不得更改变量的指针指向,除非使用__block。但是,对对象内部的值进行更改是没有问题的,就像这段代码[string0 appendString:@"456”];

代码3


    int test =99;
    int *tt = &test;

    ^{
        //test = test + 9;
        *tt = *tt +9;
    }();

从上面代码可以看出,对test直接更改test = test + 9;违背了一致原则,所以报错了;

而使用指针tt 却是可以的,这是因为使用test指针时,block引用的会是指针tt,代码*tt = *tt + 9;只修改了指针指向的内存块内的值,并没有修改指针本身,这样block内外值都一样,在block结束后,test的值等于108,所以符合一致原则

你可能感兴趣的:(关于block(三)----变量引用 + __block修饰)