__weak 本身是可以避免循环引用的问题的, 但是其会导致外部对象释放了之后, block 内部也访问不到这个对象的问题.
我们可以通过在 block 内部声明一个 __strong 的变量来指向 weakObj, 使外部对象既能在 block 内部保持住, 又能避免循环引用的问题.
__block 本身无法避免循环引用的问题, 但是我们可以通过在 block 内部手动把 blockObj 赋值为 nil 的方式来避免循环引用的问题.
另外一点就是 __block 修饰的变量在 block 内外都是唯一的, 要注意这个特性可能带来的隐患.
#import <Foundation/Foundation.h>
#import "MyObject.h"
#define MLog(prefix, obj) {NSLog(@"变量内存地址:%p, 变量值:%p, 指向对象:%@, --> %@", &obj, obj, obj, prefix);}
void testWeak() {
MyObject *obj = [[MyObject alloc] init];
obj.text = @"11111111111";
MLog(@"obj", obj);
__weak MyObject *weakObj = obj;
MLog(@"weakObj", weakObj);
void (^testWeakBlock)() = ^() {
MLog(@"weakObj - block", weakObj);
};
testWeakBlock();
obj = nil;
testWeakBlock();
}
void testWeak2() {
MyObject *obj = [[MyObject alloc] init];
obj.text = @"123456789";
MLog(@"obj", obj);
__weak MyObject *weakObj = obj;
MLog(@"weakObj-0", weakObj);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
__strong MyObject *strongObj = weakObj;
sleep(4);
MLog(@"weakObj-block", weakObj);
MLog(@"strongObj-block", strongObj);
});
sleep(1);
obj = nil;
MLog(@"weakObj-1", weakObj);
sleep(4);
MLog(@"weakObj-2", weakObj);
//sleep(10);
}
void testBlock() {
MyObject *obj = [[MyObject alloc] init];
obj.text = @"1111111111";
MLog(@"obj", obj);
__block MyObject *blockObj = obj;
obj = nil;
MLog(@"blockObj", blockObj);
void(^testBlockBlock)() =^() {
MLog(@"blockObj-block", blockObj);
MyObject *obj2 = [[MyObject alloc] init];
obj2.text = @"2222222222";
MLog(@"obj2", obj2);
blockObj = obj2;
MLog(@"blockObj-block", blockObj);
};
NSLog(@"%@", testBlockBlock);
MLog(@"blockObj-2", blockObj);
testBlockBlock();
MLog(@"blockObj - 3", blockObj);
}
void testBlock2() {
MyObject *obj = [[MyObject alloc] init];
obj.text = @"1111111111";
MLog(@"obj", obj);
__block MyObject *blockObj = obj;
obj = nil;
void (^testBlock2Block)() = ^() {
MLog(@"blockObj", blockObj);
};
obj = nil;
testBlock2Block();
MLog(@"blockObj", blockObj);
}
void testBlock3() {
MyObject *obj = [[MyObject alloc] init];
obj.text = @"1111111111";
MLog(@"obj", obj);
__block MyObject *blockObj = obj;
obj = nil;
void (^testBlock3Block)() = ^() {
MLog(@"blockObj-block", blockObj);
blockObj = nil;
};
obj = nil;
testBlock3Block();
MLog(@"blockObj", blockObj);
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
//testWeak2();
testBlock3();
}
return 0;
}