使用本地范围ivars保留块内部的循环

时间:2013-09-09 22:53:55

标签: objective-c objective-c-blocks retaincount retain-cycle

对于我的生活,我无法弄清楚这里发生了什么。

作为概述,我有一个应用程序,我已经创建了一个自定义导航栏,一个自定义包含视图控制器,以及回调,告诉我何时在单个视图控制器内执行昂贵的进程(例如一大组图片)。

在导航到子视图控制器时,在我的包含视图控制器中,在子视图控制器上设置回调,以在完成它的一组昂贵进程后调用过渡动画。

回调是这样创建的

@interface UIViewController (CallBack)

typedef void (^CompletionBlock)(void);

@property (nonatomic, copy) CompletionBlock callBackBlock;

- (void)doneLoadingImages;

@end

static char const *const CompletionBlockTagKey = "CompletionBlockTag";

@implementation UIViewController (CallBack)
@dynamic callBackBlock;

- (CompletionBlock)callBackBlock
{
    return objc_getAssociatedObject(self, CompletionBlockTagKey);
}

- (void)setCallBackBlock:(CompletionBlock)callBackBlock
{
    objc_setAssociatedObject(self, CompletionBlockTagKey, callBackBlock, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (void)doneLoadingImages
{
    [self callBackBlock]();

    self.callBackBlock = nil;
}

@end

这些回调是在通过addChildViewcontroller:添加子视图控制器之前设置的,并在诸如此类的dispatch_async块中触发

__block __weak ThisUIViewController *me = self;

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    UIImage *image1 = [UIImage imageForNibFromFileName:@"picture_name"];

    dispatch_async(dispatch_get_main_queue(), ^{
        me.imageViewToSet.image = image1;

        [me doneLoadingImages];
    });
});

第一次通过我的导航代码从容器视图控制器调用UIViewcontroller时,这个过程很顺利。根据分析器,它在我离开它之后也正确地转储内存,表明我的保留计数为0。

但是,当我再次导航到相同的UIViewcontroller时会发生什么,图像加载速度超快,doneLoadingImages也被称为超快速,导致我的主线程挂起并导致UI在所有内容都设置为UI之前,它们会变得没有反应。

我的imageForNibFromFileName:方法只是一种在内部使用imageForContentsOfFile:的便捷类别方法。任何人都对我在这里做错了什么有所了解?

1 个答案:

答案 0 :(得分:0)

原来这不是保留问题。我不确定为什么,但我不得不将图像分离到他们自己的来自global_queue的dispatch_async调用,而不是将它们全部链接在一个异步块中。如果有人解释为什么要这样做或后台发生了什么,那将不胜感激。