美文网首页iOS block相关
block中访问成员变量与self的引用

block中访问成员变量与self的引用

作者: 麻辣香锅加特辣 | 来源:发表于2018-09-28 15:31 被阅读39次

    在block中直接访问成员变量和通过self.访问,block都会强引用self
    两种方式对比:
    通过 命令:clang -rewrite-objc Person.m 将oc代码转换为c++代码

    1. 直接访问成员变量
    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject
    
    @property (nonatomic, strong) NSString *name123;
    
    @end
    
    #import "Person.h"
    
    @interface Person() {
        int age123;
    }
    @end
    
    @implementation Person
    
    - (void)test {
        void (^myblock) (void) = ^{
            NSLog(@"%d", age123);
        };
    
        myblock();
    }
    @end
    

    转换为c++的代码:

    // @implementation Person
    struct __Person__test_block_impl_0 {
      struct __block_impl impl;
      struct __Person__test_block_desc_0* Desc;
      //这里有个self
      Person *self;
      __Person__test_block_impl_0(void *fp, struct __Person__test_block_desc_0 *desc, Person *_self, int flags=0) : self(_self) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    static void __Person__test_block_func_0(struct __Person__test_block_impl_0 *__cself) {
          Person *self = __cself->self; // bound by copy
    
           //猜测是通过self + 偏移量访问到成员变量
           NSLog((NSString *)&__NSConstantStringImpl__var_folders_y6_mv_x0lbx2qs9dvbg7g9_sk780000gn_T_Person_bd97ae_mi_0, 
                (*(int *)((char *)self + OBJC_IVAR_$_Person$age123)));
        }
    
    1. 通过点语法访问
    @implementation Person
    
    - (void)test {
        void (^myblock) (void) = ^{
            NSLog(@"%@", self.name123);
        };
        
        myblock();
    }
    @end
    

    转换为c++的代码:

    // @implementation Person
    
    
    struct __Person__test_block_impl_0 {
      struct __block_impl impl;
      struct __Person__test_block_desc_0* Desc;
      //这里也有个self
      Person *self;
      __Person__test_block_impl_0(void *fp, struct __Person__test_block_desc_0 *desc, Person *_self, int flags=0) : self(_self) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
      }
    };
    static void __Person__test_block_func_0(struct __Person__test_block_impl_0 *__cself) {
         Person *self = __cself->self; // bound by copy
    
         //通过消息发送的方式,调用getter方法访问成员变量
         NSLog((NSString *)&__NSConstantStringImpl__var_folders_y6_mv_x0lbx2qs9dvbg7g9_sk780000gn_T_Person_487e48_mi_0, 
              ((NSString *(*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("name123")));
        }
    

    通过转换后的代码可以看出来,无论通过那种方式访问最终都需要使用self,所以block都会强引用self。

    相关文章

      网友评论

        本文标题:block中访问成员变量与self的引用

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