将NSOperation添加到NSOperationQueue时的EXC_BAD_ACCESS

时间:2012-09-25 09:31:45

标签: iphone ios multithreading nsoperation nsoperationqueue

我已经在这个错误上坐了好几个小时了。我在行上获得了EXC_BAD_ACCESS(代码= 2):

[self.downloadQueue addOperation:self.downloadOP];

我知道它必须与内存冲突有关,但我找不到问题。管理OperationQueues的类是一个单例,但我认为这不是问题。

这是我的.h文件的简化版本:

@interface GTMConnectionManager : NSObject{
}

@property (retain) GTMDownloadOperation *downloadOP;
@property (retain) NSOperationQueue *downloadQueue;
// it doesn't make a difference if I add 'nonatomic' to these properties

+ (GTMConnectionManager *)sharedConnectionManager;
-(void)downloadImageData:(NSMutableArray*)p_images andController:(UIViewController*)p_resultsController;

@end

.m文件的重要部分:

#import "GTMConnectionManager.h"
@implementation GTMConnectionManager
@synthesize downloadOP, downloadQueue;

+ (GTMConnectionManager *)sharedConnectionManager
{
    static GTMConnectionManager * instance = nil;

    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        instance = [[super allocWithZone:nil] init];
    });
    return instance;
}

-(void)downloadImageData:(NSMutableArray*)p_images andController:(GTMResultsListViewController*)p_resultsController{

    self.resultsController = p_resultsController;

    [self.downloadQueue setMaxConcurrentOperationCount:2];
    self.downloadQueue = [[[NSOperationQueue alloc]init]autorelease];
    // it doesn't make a difference if I do this with or without 'autorelease'

    for (int i = 0; i < [p_images count]; i++) {
        GTMGeoImage *tmpImg = [p_images objectAtIndex:i];
        self.downloadOP = [[[GTMDownloadOperation alloc]initWithImage:tmpImg]autorelease];
        [self.downloadQueue addOperation:self.downloadOP]; //Here's the error
    }
}

当我在错误行之前添加断点时,self.downloadQueue和self.downloadOP都会正确保留(不是nil)。

奇怪的是:在这个课程中,我有第二个NSOperationQueue与其他NSOperations一样,以与downloadQueue和downloadOP相同的方式声明和处理。而且他们工作得很好。

是的,GTMDownloadOperation是NSOperation的子类,并且有一个 - (void)main方法。

我现在不知道该怎么办。如果您不知道该错误的原因,我该如何更准确地分析情况? (产品&gt; Analyze不会抱怨该位置的潜在泄漏)。

感谢您的帮助。

4 个答案:

答案 0 :(得分:1)

哦,伙计...... 这需要一段时间,但最后我知道问题出现在for循环中。

声明

self.downloadOP = [[[GTMDownloadOperation alloc]initWithImage:tmpImg]autorelease];

在每次迭代中一次又一次地访问变量downloadOP。使用相同的NSOperation似乎会使其retainCount崩溃。

我把它改成了

GTMDownloadOperation *downloadOP = [[GTMDownloadOperation alloc]initWithImage:tmpImg];

它没有错误。傻我。

答案 1 :(得分:1)

你没有在构造函数中调用[super init]?

假设您正在继承NSOperation(或NSObject等...),您可能应该这样做!

答案 2 :(得分:0)

为什么要重新分配并初始化队列? 不可能只是你的单身人士课程吗?

和...

[self.downloadQueue setMaxConcurrentOperationCount:2];
self.downloadQueue = [[[NSOperationQueue alloc]init]autorelease];

第一行在旧队列上执行,然后创建一个没有限制的新行

何时调用第二行(分配新队列),释放旧行(如果有)

试试这个:

if (!downloadQueue){
    self.downloadQueue = [[[NSOperationQueue alloc]init]autorelease];
}
[self.downloadQueue setMaxConcurrentOperationCount:2];

并记得添加:

self.downloadQueue = nil;
你的dealloc方法中的

(即使它是一个单例,在你的应用程序运行时也不会被调用)

答案 3 :(得分:0)

我认为问题在于您的操作的实施。我建议两个课程:尝试创建一些简单的基于块的操作,只记录hello world并将它们添加到队列中。他们很可能会工作,让你知道队列是否正常运行。然后开始向您的子类添加日志消息,以查看调用哪些方法并正确完成。

这会引导你解决问题。