我们先来一个Demo
#import <Foundation/Foundation.h>
#define WEAKSELF() __weak __typeof(self) weakSelf = self;
#define STRONGSELF() if(!weakSelf) return ; __strong __typeof(weakSelf) self = weakSelf;
@interface DemoObject :NSObject
{
void(^block)(void);
}
@property (strong, nonatomic)NSString *myname;
@end
@implementation DemoObject
- (void)test
{
WEAKSELF()
block = ^void(void){
STRONGSELF()
NSLog(@"%@",self.myname);
};
block();
}
- (void)dealloc
{
NSLog(@" DemoObjet dealloc!!");
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
DemoObject *demoObj = [DemoObject new];
demoObj.myname = @"hello!";
[demoObj test];
}
[[NSRunLoop currentRunLoop] run];
return 0;
}
运行结果
2022-06-19 17:17:18.082107+0800 BlockSelf[1847:53701] hello!
2022-06-19 17:17:18.082606+0800 BlockSelf[1847:53701] DemoObjet dealloc!!
DemoObjet被释放了,说明没有引起循环引用。主要是STRONGSELF宏将声明了一个self的局域变量,解除了循环引用链。
接下来我们将代码改一下
- (void)test
{
WEAKSELF()
block = ^void(void){
STRONGSELF()
NSLog(@"%@",_name); //这里改成_name
};
block();
}
输出结果
2022-06-19 17:18:39.747908+0800 BlockSelf[1861:55035] hello!
DemoObjet没有释放。
也就是说我们在block里面将.self.name改成了_name导致了循环引用。
按理说_name 等同于self->_name ,而self已经被STRONGSELF 定义成了局部变量。那为什么会出现循环引用呢?
我们使用clang将OC转成C/C++代码
clang -rewrite-objc -fobjc-arc -fobjc-runtime=macosx-10.14 main.m
目录下会出现main.cpp
struct __DemoObject__test_block_impl_0 {
struct __block_impl impl;
struct __DemoObject__test_block_desc_0* Desc;
DemoObject *const __weak weakSelf;
__DemoObject__test_block_impl_0(void *fp, struct __DemoObject__test_block_desc_0 *desc, DemoObject *const __weak _weakSelf, int flags=0) : weakSelf(_weakSelf) {
impl.isa = &_NSConcreteStackBlock;
impl.Flags = flags;
impl.FuncPtr = fp;
Desc = desc;
}
};
可以看到这句
DemoObject *const __weak weakSelf; 确实是__weak,那为什么还是会循环引用了呢?