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。

时间: 2024-09-14 06:57:39

block循环引用解决的相关文章

ios block-IOS block强引用循环问题,下面的代码为什么能避免强引用循环

问题描述 IOS block强引用循环问题,下面的代码为什么能避免强引用循环 下面的代码为什么能避免强引用循环? cell.thumbnailView.image = item.thumbnail; __weak BNRItemCell *weakCell = cell; cell.actionBlock = ^{ NSLog(@"Going to show image for %@", item); BNRItemCell *strongCell = weakCell; if ([U

Entity Framework对象序列化出错:检测到循环引用

ASP.NET MVC3中尝试将Entity Framework对象序列化输出,结果出错,代码如下:  代码如下 复制代码  public ActionResult Index() {     testContext context = new testContext();     var data = context.People;     return Json(data, JsonRequestBehavior.AllowGet); } 错误信息:  引用内容 序列化类型为"System.

iOS - NSTimer循环引用的解决办法

发生场景 在 Controller B 中有一个 NSTimer @property (strong, nonatomic) NSTimer *timer;  你创建了它,并挂载到 main runloop self.timer = [NSTimer scheduledTimerWithTimeInterval:1   target:self selector:@selector(timerAction:) userInfo:nil repeats:true];  然后退出 Controller

Unity Application Block 1.0系列(6):杜绝循环引用

在介绍 Constructor Injection.Property Injection和 Method Call Injection时,都有特别提到不要出现循环引用(Circular References),因为出现这种问题后很难去检测到.最好的解决方法是写代码时候尽量避免出现这种情况. 下面看看循环引用的几个场景,在使用依赖注入框架时应该尽量避免出现这样的情况: 1.通过Constructor Injection生成的对象在构造器的参数中互相引用 public class Class1{ p

ARC下的block导致的循环引用问题解析

ARC下的block导致的循环引用问题解析 更详细细节请参考 http://blog.sina.com.cn/s/blog_8c87ba3b0101m599.html   ARC下,copy到堆上的block,会强引用进入到该block中的外部变量.这很容易导致循环引用的问题. 比方说: 一个VC(这里指一个controller)中有一个属性为model.VC强引用了它. VC --> model 这个model呢,里面有一个copy属性的block,该block赋值如下如下.model.dem

block使用小结、在arc中使用block、如何防止循环引用(zz)

标签:  __block   __weak   arc   self   cfgetretaincount 分类: iOS zz from http://www.cnbluebox.com/?p=255 引言 使用block已经有一段时间了,感觉自己了解的还行,但是几天前看到CocoaChina上一个关于block的小测试主题: [小测试]你真的知道blocks在Objective-C中是怎么工作的吗?,发现竟然做错了几道, 才知道自己想当然的理解是错误的,所以抽时间学习了下,并且通过一些测试代

解决循环引用的一个例子

最近在讨论设计时注意到一个循环引用的问题.它是在使用引用计数指针时发生的.如下图所示: ClassA和ClassB分属两个不同的线程,ClassB通常由ClassA发起请求创建,并由ClassA使用,ClassB则会在必要时通知ClassA一些事件.两者中各保留了对方的一个引用计数指针RefPtr. 如果在析构时释放成员变量的话,就会发生循环引用的问题,导致两个对象释放失败.   最直接的解决方法(不考虑弱引用指针)就是将释放指针的操作显示定义成函数,与析构函数分离开来,并在析构前确保调用这个函

如何避免在Block里用self造成循环引用

一般来说我们总会在设置Block之后,在合适的时间回调Block,而不希望回调Block的时候Block已经被释放了,所以我们需要对Block进行copy,copy到堆中,以便后用. 当一个Block被Copy的时候,如果你在Block里进行了一些调用,那么将会有一个强引用指向这些调用方法的调用者,有两个规则: 如果你是通过引用来访问一个实例变量,那么将强引用至self 如果你是通过值来访问一个实例变量,那么将直接强引用至这个"值"变量 苹果官方文档里有两个例子来说明这两种情况: 上面

解决ARC的循环引用问题

看看下面的程序有什么问题: BNRItem.h @interface BNRItem : NSObject @property (nonatomic, strong) BNRItem *containedItem; @property (nonatomic, strong) BNRItem *container; ... @end   BNRItem.m #import "BNRItem.h" @implementation BNRItem ... - (void)setContain