关于weak解除block循环引用的疑问?

环境:ARC
命令:clang -rewrite-objc -fobjc-arc -stdlib=libc++ -mmacosx-version-min=10.7 -fobjc-runtime=macosx-10.7 -Wno-deprecated-declarations AnyThing.m

  • strong self
#import 
@interface AnyThing : NSObject
@end

#import "AnyThing.h"
@implementation AnyThing
- (void)someAct{
    void (^test)() = ^ {
        NSLog(@"%@",self);
    };
    test();
}
@end
// @implementation AnyThing


struct __AnyThing__someAct_block_impl_0 {
    struct __block_impl impl;
    struct __AnyThing__someAct_block_desc_0* Desc;
    AnyThing *const __strong self;//<<<不同
    __AnyThing__someAct_block_impl_0(void *fp, struct __AnyThing__someAct_block_desc_0 *desc, AnyThing *const __strong _self, int flags=0) : self(_self) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
    }
};

static void __AnyThing__someAct_block_func_0(struct __AnyThing__someAct_block_impl_0 *__cself) {
    AnyThing *const __strong self = __cself->self; // bound by copy
    
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_qp_p2pj3jmj65n39jgl4wx9_l9w0000gn_T_AnyThing_51e757_mi_0,self);
}

static void __AnyThing__someAct_block_copy_0(struct __AnyThing__someAct_block_impl_0*dst, struct __AnyThing__someAct_block_impl_0*src) {
_Block_object_assign((void*)&dst->self, (void*)src->self, 3/*BLOCK_FIELD_IS_OBJECT*/);
}

static void __AnyThing__someAct_block_dispose_0(struct __AnyThing__someAct_block_impl_0*src) {
_Block_object_dispose((void*)src->self, 3/*BLOCK_FIELD_IS_OBJECT*/);
}

static struct __AnyThing__someAct_block_desc_0 {
    size_t reserved;
    size_t Block_size;
    void (*copy)(struct __AnyThing__someAct_block_impl_0*, struct __AnyThing__someAct_block_impl_0*);
    void (*dispose)(struct __AnyThing__someAct_block_impl_0*);
} __AnyThing__someAct_block_desc_0_DATA = { 0, sizeof(struct __AnyThing__someAct_block_impl_0), __AnyThing__someAct_block_copy_0, __AnyThing__someAct_block_dispose_0};

static void _I_AnyThing_someAct(AnyThing * self, SEL _cmd) {
 void (*test)() = ((void (*)())&__AnyThing__someAct_block_impl_0((void *)__AnyThing__someAct_block_func_0, &__AnyThing__someAct_block_desc_0_DATA, self, 570425344));
 ((void (*)(__block_impl *))((__block_impl *)test)->FuncPtr)((__block_impl *)test);
}

// @end
  • weak self
#import 
@interface AnyThing : NSObject
@end

#import "AnyThing.h"
@implementation AnyThing
- (void)someAct{
    __weak __typeof(&*self)weakSelf = self;
    void (^test)() = ^ {
        NSLog(@"%@",weakSelf);
    };
    test();
}
@end
// @implementation AnyThing


struct __AnyThing__someAct_block_impl_0 {
    struct __block_impl impl;
    struct __AnyThing__someAct_block_desc_0* Desc;
    __weak typeof (&*self) weakSelf;//<<<不同
    __AnyThing__someAct_block_impl_0(void *fp, struct __AnyThing__someAct_block_desc_0 *desc, __weak typeof (&*self) _weakSelf, int flags=0) : weakSelf(_weakSelf) {
        impl.isa = &_NSConcreteStackBlock;
        impl.Flags = flags;
        impl.FuncPtr = fp;
        Desc = desc;
    }
};

static void __AnyThing__someAct_block_func_0(struct __AnyThing__someAct_block_impl_0 *__cself) {
    __weak typeof (&*self) weakSelf = __cself->weakSelf; // bound by copy
    
    NSLog((NSString *)&__NSConstantStringImpl__var_folders_qp_p2pj3jmj65n39jgl4wx9_l9w0000gn_T_AnyThing_fda013_mi_0,weakSelf);
}

static void __AnyThing__someAct_block_copy_0(struct __AnyThing__someAct_block_impl_0*dst, struct __AnyThing__someAct_block_impl_0*src) {
_Block_object_assign((void*)&dst->weakSelf, (void*)src->weakSelf, 3/*BLOCK_FIELD_IS_OBJECT*/);
}

static void __AnyThing__someAct_block_dispose_0(struct __AnyThing__someAct_block_impl_0*src) {
_Block_object_dispose((void*)src->weakSelf, 3/*BLOCK_FIELD_IS_OBJECT*/);
}

static struct __AnyThing__someAct_block_desc_0 {
    size_t reserved;
    size_t Block_size;
    void (*copy)(struct __AnyThing__someAct_block_impl_0*, struct __AnyThing__someAct_block_impl_0*);
    void (*dispose)(struct __AnyThing__someAct_block_impl_0*);
} __AnyThing__someAct_block_desc_0_DATA = { 0, sizeof(struct __AnyThing__someAct_block_impl_0), __AnyThing__someAct_block_copy_0, __AnyThing__someAct_block_dispose_0};

static void _I_AnyThing_someAct(AnyThing * self, SEL _cmd) {
 __attribute__((objc_ownership(weak))) __typeof(&*self)weakSelf = self;
 void (*test)() = ((void (*)())&__AnyThing__someAct_block_impl_0((void *)__AnyThing__someAct_block_func_0, &__AnyThing__someAct_block_desc_0_DATA, weakSelf, 570425344));
 ((void (*)(__block_impl *))((__block_impl *)test)->FuncPtr)((__block_impl *)test);
}

// @end

根据上面的不同,知道:

strong
struct __AnyThing__someAct_block_impl_0对self保持强引用
weak
struct __AnyThing__someAct_block_impl_0对self保持弱引用

strong weak 对捕获对象的拷贝,传入flag一模一样

static void __AnyThing__someAct_block_copy_0(struct __AnyThing__someAct_block_impl_0*dst, struct __AnyThing__someAct_block_impl_0*src) {
_Block_object_assign((void*)&dst->self, (void*)src->self, 3/*BLOCK_FIELD_IS_OBJECT*/);
}
static void __AnyThing__someAct_block_copy_0(struct __AnyThing__someAct_block_impl_0*dst, struct __AnyThing__someAct_block_impl_0*src) {
_Block_object_assign((void*)&dst->weakSelf, (void*)src->weakSelf, 3/*BLOCK_FIELD_IS_OBJECT*/);
}
void _Block_object_assign(void *destAddr, const void *object, const int flags) {
    //printf("_Block_object_assign(*%p, %p, %x)\n", destAddr, object, flags);
    ......
    else if ((flags & BLOCK_FIELD_IS_OBJECT) == BLOCK_FIELD_IS_OBJECT) {
        //printf("retaining object at %p\n", object);
        _Block_retain_object(object);//加引用计数?
        //printf("done retaining object at %p\n", object);
        _Block_assign((void *)object, destAddr);
    }
}

strong self 加引用计数,可以理解!
weak self 加引用计数,是不是有些矛盾?


不要奇怪,ARC环境有了更完善的内存管理,如果外部变量由__strongcopystrong修饰时,Block会把捕获的变量用__strong来修饰进而达到持有的目的.这里的_Block_retain_object只不过是一个空操作.
以下代码见于BlocksRuntime/runtime.c

static void (*_Block_retain_object)(const void *ptr) = _Block_retain_object_default;
static void _Block_retain_object_default(const void *ptr __unused) {
}

分割线很好的隔开了疑问与回答,在此特别感谢解开我疑惑的啊哈呵同学.

你可能感兴趣的:(关于weak解除block循环引用的疑问?)