block循环引用解决

简介: block循环引用解决

block循环引用解决

实验代码


@interface ViewController ()
@property (nonatomic, strong) TestNetworkBlock *testNetwork;
@end

@implementation ViewController

(void)viewDidLoad {

[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

self.testNetwork = [[TestNetworkBlock alloc] init];

[self.testNetwork ceshi];
[self.testNetwork release], self.testNetwork = nil;

}

@end

@interface TestNetworkBlock ()
{

countBlock _countBlock;

}

@property (nonatomic, strong) NSString *strTest;

@end

@implementation TestNetworkBlock

(id) init
{
self = [super init];
if (self)
{

self.strTest = @"我的测试";
__weak TestNetworkBlock *weakSelf = self;
_countBlock = ^(int i){
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
        sleep(5);
        NSString *string = [weakSelf zhixing:i];
        NSLog(@"string=====%@", string);
    });
};

}
return self;
}

(NSString *) zhixing:(int) i
{
NSString *string = [NSString stringWithFormat:@"%@%d", self.strTest, i];

return string;
}

(void) ceshi
{
_countBlock(5);
}(void) dealloc
{
NSLog(@"======dealloc");
}

@end

问题剖析:

多线程调用,block外面声明了weakSelf,则block内部对self的引用为指针引用,当外部[self.testNetwork release], self.testNetwork = nil;时,weakSelf为nil,所以导致运行失败。

第二种:block改为self引用


_countBlock = ^(int i){
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
            sleep(5);
            NSString *string = [self zhixing:i];
            NSLog(@"string=====%@", string);
        });
    };

问题剖析

_countBlock为self对象,self强引用了_countBlock,同时_countBlock又怕里面self释放,所以block体里面会强引用self。导致循环引用,内存一直不会被释放,dealloc也不会被调用。

正确做法:block内部加入bSelf强引用指针


__weak TestNetworkBlock *weakSelf = self;
_countBlock = ^(int i){
        TestNetworkBlock *bSelf = weakSelf;
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
            sleep(5);
            NSString *string = [bSelf zhixing:i];
            NSLog(@"string=====%@", string);
        });
    };

问题剖析

在 block 之前定义对 self 的一个弱引用 wSelf,因为是弱引用,所以当 self 被释放时 wSelf 会变为nil;
在block体内部声明一个强引用对象bself指向该wSelf。bSelf只会在block内部执行完毕才会消亡,这样就保证了self对象被外部其他线程释放掉的情况。又避免了循环引用,因为在block执行完,会释放掉bSelf。

相关文章
|
6月前
|
C++
记录一次循环引用的问题
记录一次循环引用的问题
shared_ptr能和基于引用计数的智能指针混用吗?
shared_ptr能和基于引用计数的智能指针混用吗?
|
6月前
shared_ptr循环引用问题以及解决方法
shared_ptr循环引用问题以及解决方法
169 0
|
存储 缓存 iOS开发
(转)谈weak对象、对象缓存以及Tagged Pointer
(转)谈weak对象、对象缓存以及Tagged Pointer
53 0
|
存储 Python
独自画的【对象的内存结构】
独自画的【对象的内存结构】 其实每个对象都有三种数据: id(标识) type(类型) value(值)
93 0
独自画的【对象的内存结构】
你知道block循环引用怎么解决了吗?
在使用block的时候,最需要注意的问题便是循环引用,这节主要讲解,block是如何产生的?碰到循环引用又该怎么解决。
171 0
你知道block循环引用怎么解决了吗?
|
iOS开发
block的循环引用分析
block的循环引用分析
137 0
block的循环引用分析
|
程序员 开发者
block有哪些对象类型,你知道了吗?
从block的本质这篇文章中,我们已经知道block的本质是一个OC对象。既然是OC对象。那肯定有对象类型,还是从block的本质这篇文章中搜索impl.ipa字段,发现block指向了一个对象 _NSConcreteStackBlock。那么block还有什么类型呢?怎么实现呢?它们又是分配在哪些内存区呢?让我们带着这些疑问往下看。
186 0
block有哪些对象类型,你知道了吗?
Block循环引用
Block循环引用
93 0
|
iOS开发
iOS开发:block死循环及__weak弱引用提前释放的问题解决
block死循环及__weak弱引用提前释放的问题解决
320 0