美文网首页
Objective-C基础之*_ weak, _* strong

Objective-C基础之*_ weak, _* strong

作者: Harry_Coding | 来源:发表于2018-05-17 19:01 被阅读17次

    上一篇文章中对于block做了一个全面的剖析和理解,那么在OBjective—C的block使用中我们难免会用到以上几个关键字,其实对于_block上篇文章已经做了解释,这篇文章,我会做几个关键字的区别和总结,来加深认识和理解。
    *上篇文章知道 clang -rewrite-objc 可以将OC代码转化成C代码C++代码,如果变量加上
    weak修饰,会发现无法转化,提示:cannot create _* weak reference because the current deployment target does not support weak references 我们需要这样解决这个问题:clang -rewrite-objc -fobjc-arc -fobjc-runtime=macosx-10.13 main.m -fobjc-arc代表当前是arc环境 -fobjc-runtime=macosx-10.13:代表当前运行时环境 缺一不可 clang指令**

    .m 源码
    int main(int argc, char * argv[]) {
    //    @autoreleasepool {
        //        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    int a = 10;
    int b = 20;
    NSNumber *c = @(123);
    __block NSNumber *d = c;
    __weak NSNumber *f = c;
    void (^myBlock)(void) = ^{
        __strong NSNumber *e = f;
        NSLog(@"hello world %d, %d, %@, %@, %@, %@", a, b, c, d, f, e);
    };
    myBlock();
    //    }
    return 0;
    }
    转化成c代码
    // block 结构体
    struct __main_block_impl_0 {
      struct __block_impl impl;
      struct __main_block_desc_0* Desc;
      int a;
      int b;
      NSNumber *__strong c;
      NSNumber *__weak f;
      __Block_byref_d_0 *d; // by ref
      __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int _b, NSNumber *__strong _c, NSNumber *__weak _f, __Block_byref_d_0 *_d, int flags=0) : a(_a), b(_b), c(_c), f(_f), d(_d->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
      }
    };
    // 我们可以看到没有__block修饰的变量和__weak修饰的对象,都没有重新生成一个__Block_byref_d_0 的结构体,只有__block修饰的才会生成这样的结构体
    int main(int argc, char * argv[]) {
    
    int a = 10;
    int b = 20;
    NSNumber *c = ((NSNumber *(*)(Class, SEL, int))(void *)objc_msgSend)(objc_getClass("NSNumber"), sel_registerName("numberWithInt:"), (123));
    __attribute__((__blocks__(byref))) __Block_byref_d_0 d = {(void*)0,(__Block_byref_d_0 *)&d, 33554432, sizeof(__Block_byref_d_0), __Block_byref_id_object_copy_131, __Block_byref_id_object_dispose_131, c};
    __attribute__((objc_ownership(weak))) NSNumber *f = c;
    void (*myBlock)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, f, a, b, c, (__Block_byref_d_0 *)&d, 570425344));
    ((void (*)(__block_impl *))((__block_impl *)myBlock)->FuncPtr)((__block_impl *)myBlock);
    
    return 0;
    }
    struct __Block_byref_d_0 {
      void *__isa;
    __Block_byref_d_0 *__forwarding;
     int __flags;
     int __size;
     void (*__Block_byref_id_object_copy)(void*, void*);
     void (*__Block_byref_id_object_dispose)(void*);
     NSNumber *__strong d;
    };
    
    // 我们可以看到没有加__block的变量,在捕获之后,都会copy出来,不管是值类型还是引用类型的,所以不可以改变内容
    static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
      __Block_byref_d_0 *d = __cself->d; // bound by ref
      NSNumber *__weak f = __cself->f; // bound by copy
      int a = __cself->a; // bound by copy
      int b = __cself->b; // bound by copy
      NSNumber *__strong c = __cself->c; // bound by copy
    
        __attribute__((objc_ownership(strong))) NSNumber *e = f;
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_dr_jkts5c395zs9xcx0bt_r7fx40000gn_T_main_188e34_mi_0, a, b, c, (d->__forwarding->d), f, e);
    }
    
    

    通过上述的源码,我们可以看出,只有__ block 修饰的局部变量才会生成一个结构体,这个结构体包含了变量,而block的结构体则是一个变成了结构体的指针,所以内部修改指针指向内容是可以的,而对于没有修饰的变量,值变量则是重新声明一个变量赋值相同,引用类型则是重新申明变量,指针copy,所以在内部都是无法修改外部变量的值的。

    综上所述,__ block :修饰的外部局部变量值和引用类型,都会重新生成包裹该变量的结构体,block本质结构体会声明这个结构体的指针,所以可以直接修改外部局部变量;可修饰值变量和引用变量(即普通类型和对象类型的变量);
    没有修饰的变量:值类型和引用类型都会重新生成一个变量,值类型重新生成一个变量,将局部变量的值赋值给他;引用类型的变量,生成一个新指针,指向这个指针的copy,强引用;
    weak :没有重新生成包裹变量的结构体,重新声明一个弱引用指针,指向这个指针的copy体,所以不可以在内部修改变量的值;只能修饰引用类型的变量,所以 weak 修饰可以防止循环引用;
    __strong:一般使用像如下代码

       // typeof() 函数只是返回参数的类型 
    __weak typeof(self) weakSelf = self;
    void (^myBlock)(void) = ^{
        __strong typeof(self) strongSelf = weakSelf;
    }
    
    

    block内部对变量生成一个强引用,防止在Block函数体执行过程中,变量被释放,block函数体执行完,引用计数器-1

    相关文章

      网友评论

          本文标题:Objective-C基础之*_ weak, _* strong

          本文链接:https://www.haomeiwen.com/subject/iejidftx.html