Сбой 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];
    }
}

0 ответов

Другие вопросы по тегам