将NSOperations添加到NSOperationQueue时,iOS在后台数据处理期间崩溃

时间:2014-05-06 18:22:46

标签: ios objective-c crash nsoperation nsoperationqueue

我的应用随机获取了#39;在进行一些后台数据处理时崩溃。我将NSOperations(子类)添加到数组中,然后将NSOperations的数组添加到NSOperationQueue

我看到3-4个错误都指向堆栈跟踪中的这一行:

[_operationQueue addOperations:_operationsArray waitUntilFinished:YES];

以下是我创建NSOperationsLibSyncOperation)并将其添加到_operationsArray的方式,最终会添加到_operationQueue

LibSyncOperation *libSyncOperation = [[LibSyncOperation alloc] initWithURL:path];    
if(!libSyncOperation.isExecuting && !libSyncOperation.isFinished)
{
    [_operationsArray addObject:libSyncOperation];
    TFLog(@"Operation is *NOT* Executing, add to OperationQueue");
}
else
{
    TFLog(@"Operation is already Executing, do not add to OperationQueue");
}

以下是一些堆栈跟踪:

*** -[NSOperationQueue addOperations:waitUntilFinished:]: 3 (of 4) operations are finished, executing, or already in a queue, and cannot be enqueued
CoreFoundation-[NSException initWithCoder:]

0   CoreFoundation  0x18835f09c __exceptionPreprocess
1   libobjc.A.dylib 0x1947b5d78 objc_exception_throw
2   CoreFoundation  0x18835efdc -[NSException initWithCoder:]
3   Foundation  0x188ec1864 __addOperations
4   Foundation  0x188ec1bfc -[NSOperationQueue addOperations:waitUntilFinished:]
5   Tower-iSales-Tab    0x100223b54 __70-[NetworkManager checkForDataFilesShouldEmptyQueue:isInitialDownload:]_block_invoke_2183 in NetworkManager.m on Line 437
6   libdispatch.dylib   0x194d84420 _dispatch_call_block_and_release
7   libdispatch.dylib   0x194d843e0 _dispatch_client_callout
8   libdispatch.dylib   0x194d8b3fc _dispatch_root_queue_drain
9   libdispatch.dylib   0x194d8b638 _dispatch_worker_thread2
10  libsystem_pthread.dylib 0x194f19918 _pthread_wqthread
11  libsystem_pthread.dylib 0x194f197a8 start_wqthread

另:

*** Collection <__NSMallocBlock__: 0x1784402a0> was mutated while being enumerated.
CoreFoundation

0   CoreFoundation  0x186226f50 
1   libobjc.A.dylib 0x192c041fc objc_exception_throw
2   CoreFoundation  0x186226984 
3   Foundation  0x186d91928 -[NSOperationQueue addOperations:waitUntilFinished:]
4   Tower-iSales-Tab    0x1002bbb54 __70-[NetworkManager checkForDataFilesShouldEmptyQueue:isInitialDownload:]_block_invoke_2183 in NetworkManager.m on Line 437
5   libdispatch.dylib   0x1931dc014 _dispatch_call_block_and_release
6   libdispatch.dylib   0x1931dbfd4 _dispatch_client_callout
7   libdispatch.dylib   0x1931e32b8 _dispatch_root_queue_drain
8   libdispatch.dylib   0x1931e34fc _dispatch_worker_thread2
9   libsystem_pthread.dylib 0x1933716bc _pthread_wqthread
10  libsystem_pthread.dylib 0x19337154c start_wqthread

最后一个:

-[__NSBlockVariable__ countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x1782499c0
CoreFoundation__methodDescriptionForSelector


0   CoreFoundation  0x18835f09c __exceptionPreprocess
1   libobjc.A.dylib 0x1947b5d78 objc_exception_throw
2   CoreFoundation  0x188363d14 __methodDescriptionForSelector
3   CoreFoundation  0x188361a7c ___forwarding___
4   CoreFoundation  0x1882814ac __forwarding_prep_0___
5   Foundation  0x188ec1ca0 -[NSOperationQueue addOperations:waitUntilFinished:]
6   Tower-iSales-Tab    0x1002afb54 __70-[NetworkManager checkForDataFilesShouldEmptyQueue:isInitialDownload:]_block_invoke_2183 in NetworkManager.m on Line 437
7   libdispatch.dylib   0x194d84420 _dispatch_call_block_and_release
8   libdispatch.dylib   0x194d843e0 _dispatch_client_callout
9   libdispatch.dylib   0x194d8b3fc _dispatch_root_queue_drain
10  libdispatch.dylib   0x194d8b638 _dispatch_worker_thread2
11  libsystem_pthread.dylib 0x194f19918 _pthread_wqthread
12  libsystem_pthread.dylib 0x194f197a8 start_wqthread

是否会出现这种崩溃的明显原因?我理解错误消息的内容,正在执行或已完成的NSOperations无法再次排队,事实是,我的_operationsArray会在更新过程运行时重新分配,以确保没有已经排队的NSOperations

我没有做的一件事,就是每次重新分配NSOperationQueue,我认为这可能是原因,但由于我无法在我的最终重现错误(用户正在经历这个),我想知道当然。下面是我的NSOperationQueue的代码(请注意,这只是一个单例类)

    if(!_operationQueue)
        _operationQueue = [[NSOperationQueue alloc]init];

    [_operationQueue setMaxConcurrentOperationCount:1];

这可能是罪魁祸首吗?

任何建议表示赞赏。感谢。

修改

根据要求,继承了我的LibSyncOperation的main

-(void)main
{
    if (![self isCancelled])
    {
        [self willChangeValueForKey:@"isExecuting"];
        executing = YES;

        NSURLRequest *downloadRequest = [NSURLRequest requestWithURL:downloadURL cachePolicy:nil timeoutInterval:9999999];

        NSURLConnection *downloadConnection = [[NSURLConnection alloc] initWithRequest:downloadRequest delegate:self];

        [downloadConnection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
        [downloadConnection start]; 

        if (downloadConnection) 
        {
            do
            {
                [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
            } while (!downloadDone);

            [self terminateOperation];
        }
        else
        {
            [self terminateOperation];
        }
    }
    else
    {
        [self terminateOperation];
    }
}

0 个答案:

没有答案