Сбой iOS во время фоновой обработки данных при добавлении NSOperations в NSOperationQueue
Мое приложение получает "случайный" сбой при выполнении некоторой фоновой обработки данных. Я добавляю 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];
Может ли это быть виновником?
Любой совет приветствуется. Благодарю.
РЕДАКТИРОВАТЬ
Как и просили, вот main
для моей LibSyncOperation:
-(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];
}
}