zoukankan      html  css  js  c++  java
  • Objective-C基础之_ weak, _ strong , __ block

     

    上一篇文章中对于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

     
     
     
     

  • 相关阅读:
    LintCode Python 简单级题目 488.快乐数
    LintCode Python 简单级题目 100.删除排序数组中的重复数字 101.删除排序数组中的重复数字II
    LintCode Python 简单级题目 373.奇偶分割数组
    LintCode Python 简单级题目 39.恢复旋转排序数组
    LintCode Python 简单级题目 35.翻转链表
    LintCode Python 简单级题目 451.两两交换链表中的节点
    LintCode Python 简单级题目 174.删除链表中倒数第n个节点
    aws查看官方centos镜像imageid
    linux shell脚本查找重复行/查找非重复行/去除重复行/重复行统计
    php配置优化-生产环境应用版
  • 原文地址:https://www.cnblogs.com/wannaGoBoy/p/9052700.html
Copyright © 2011-2022 走看看