我的应用随机获取了#39;在进行一些后台数据处理时崩溃。我将NSOperations
(子类)添加到数组中,然后将NSOperations
的数组添加到NSOperationQueue
。
我看到3-4个错误都指向堆栈跟踪中的这一行:
[_operationQueue addOperations:_operationsArray waitUntilFinished:YES];
以下是我创建NSOperations
(LibSyncOperation
)并将其添加到_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];
}
}