__block与__weak的区别,block使用注意点

/*

 使用了__weak修饰符的对象,作用等同于定义为weakproperty。自然不会导致循环引用问题,因为苹果文档已经说的很清楚,当原对象没有任何强引用的时候,弱引用指针也会被设置为nil;

 因此,__block__weak修饰符的区别其实是挺明显的:

 1.__block不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。

 2.__weak只能在ARC模式下使用,也只能修饰对象(NSString),不能修饰基本数据类型(int)。

 3.__block对象可以在block中被重新赋值,__weak不可以。

 PS__unsafe_unretained修饰符可以被视为iOS SDK 4.3以前版本的__weak的替代品,不过不会被自动置空为nil。所以尽可能不要使用这个修饰符。

 */


block使用注点点:

    // 1.block中可以访问外面的变量

    /*

    int a = 10;

    void (^myBlock)() = ^{

        NSLog(@"a = %i", a);

    };

    myBlock();

    */

    

    // 2.block中可以定义和外界同名的变量, 并且如果在block中定义了和外界同名的变量, block中访问的是block中的变量

    /*

    int a = 10;

    void (^myBlock)() = ^{

        int a  = 20;

        NSLog(@"a = %i", a);

    };

    myBlock();

     */

    

    // 3.默认情况下, 不可以在block中修改外界变量的值

    // 因为block中的变量和外界的变量并不是同一个变量

    // 如果block中访问到了外界的变量, block会将外界的变量拷贝一份到堆内存中

    // 因为block中使用的外界变量是copy, 所以在调用之前修改外界变量的值, 不会影响到blockcopy的值

    /*

    int a = 10;

    NSLog(@"&a = %p", &a);

    void (^myBlock)() = ^{

//        a = 50;

        NSLog(@"&a = %p", &a);

        NSLog(@"a = %i", a);

    };

    a = 20;

    myBlock();

     */

    

    /*

    // 如果想在block中修改外界变量的值, 必须在外界变量前面加上__block

    // 如果在block中修改了外界变量的值, 会影响到外界变量的值

    __block int a = 10;

    NSLog(@"&a = %p", &a);

    void (^myBlock)() = ^{

        a = 50;

        NSLog(@"&a = %p", &a);

        NSLog(@"a = %i", a);

    };

    myBlock();

    NSLog(@"a = %i", a);

     */

    

    /*

    

//     int a = 10; // 如果没有添加__block是值传递

//     void (*myBlock)() = &__main_block_impl_0( __main_block_func_0, &__main_block_desc_0_DATA, a);

//     (myBlock)->FuncPtr)(myBlock);

    

    // 为什么不加__block不能在block中修改外界变量的值

    int a = 10;

    void (^myBlock)() = ^{

//        a = 10;

        NSLog(@"a = %i", a);

    };

    myBlock();

     */

    

    /*

//    a =  10; // 如果加上__block之后就是地址传递, 所以可以在block中修改外界变量的值

//    void (*myBlock)() = &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, &a, 570425344);

    

    // 为什么加了__block就可以在block中修改外界变量的值

    __block int a = 10;

    void (^myBlock)() = ^{

        a = 10;

        NSLog(@"a = %i", a);

    };

    myBlock();

     */

    

    

    // block是存储在堆中还是栈中

    // 默认情况下block存储在栈中, 如果对block进行一个copy操作, block会转移到堆中

    // 如果block在栈中, block中访问了外界的对象, 那么不会对对象进行retain操作

    // 但是如果block在堆中, block中访问了外界的对象, 那么会对外界的对象进行一次retain

    

    // 如果在block中访问了外界的对象, 一定要给对象加上__block, 只要加上了__block, 哪怕block在堆中, 也不会对外界的对象进行retain

    // 如果是在ARC开发中就需要在前面加上__weak

    __block Person *p = [[Person alloc] init]; // 1

    

    // 如果在做iOS开发时, ARC中不这样写容易导致循环引用

//    Person *p = [[Person alloc] init];

//    __weak Person *weakP = p;

    

    NSLog(@"retainCount = %lu", [p retainCount]);

    void (^myBlock)() = ^{

        NSLog(@"p = %@", p); // 2

//        NSLog(@"p = %p", weakP);

        NSLog(@"block retainCount = %lu", [p retainCount]);

    };

    Block_copy(myBlock);

    myBlock();

    

    [p release]; // 1


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值