NSOperation утечки только на устройстве iOS 3 - PullRequest
2 голосов
/ 30 сентября 2010

У меня есть несколько подклассов NSOperations, которые обрабатывают импорт CoreData.Я полагаю, что поставил галочку на большинство проблем неосновных потоков

  • Я создаю свой собственный пул автоматического выпуска в методе main
  • Я создаю NSManagedObjectContext для каждой операции

Эти операции загружаются в NSOperationQueue с максимальным числом одновременных операций, установленным в 1.

Код отлично работает на iOS 4.0.1, однако на iOS 3.1.3 устройства a получают множество сообщений журнала, таких как

*** _NSAutoreleaseNoPool(): Object 0x5f926c0 of class NSCFDictionary autoreleased with no pool in place - just leaking

Основной метод подкласса NSOperation

-(void) main{

    NSAutoreleasePool   *pool = [[NSAutoreleasePool alloc] init];

    @try {
    //Start Operation
    //====================================
    NSManagedObjectID       *objID      = nil;
    NSError             *err        = nil;
    id                              user            = nil;

    if( !(userID = [self __lookup:[self userID] inContext: [self threadContext]]) ){

        //Set the name of the element
        user = [[self threadContext] objectWithID:objID];
        //Update the name
        [user setValue:@"John Doe"  forKey:@"name"];
        [user setValue:@"Hello world" forKey:@"status"];
    }


    if( ![[self threadContext] save:&err] ){
        DebugLog(@"Couldn't savechanges %@", err);
    }

    //====================================
    //End Operation
    }
    @catch (NSException * e) {
        DebugLog(@"Exception %@",e);
    }
    //====================================


   [pool drain];
}

Метод __lookup:inContext:

-(NSManagedObjectID*) __lookup:(id)aID inContext:(NSManagedObjectContext*) aContext{

    NSPredicate             *predicate      = nil;
    NSEntityDescription     *entity;
    NSFetchRequest          *fetchRequest   = nil;
    NSError                 *err            = nil;

    predicate = [NSPredicate predicateWithFormat:@"userID == %@",aID];

    entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:aContext];

    fetchRequest = [[[NSFetchRequest alloc] init] autorelease];

    [fetchRequest setPredicate:predicate];

    [fetchRequest setEntity:entity];

    //Only fetch id's for speed
    [fetchRequest setResultType:NSManagedObjectIDResultType];

    return [[aContext executeFetchRequest:fetchRequest error:&err] lastObject];

}

Большинстводругие методы экземпляра методов, то есть threadContext выглядят аналогично __lookup:inContext: методу.Мне известно, что я не создаю пулы авто-релиза для методов экземпляра, но согласно моему пониманию того, как работает авто-релиз, до тех пор, пока эти методы вызываются только внутри основного метода, после создания NSAutoreleasePool,самый внешний бассейн должен быть использован.Я лениво создаю такие объекты, как NSManagedObjectContext, и в большинстве случаев не использую метод start

1 Ответ

0 голосов
/ 10 ноября 2010

Решено, эта операция запускала NSURLConnection, используя рекомендации из статьи Дэйва Дрибина.Однако там, где это возможно, я стараюсь никогда не вырезать и не вставлять код других людей, поэтому я всегда могу отфильтровать то, что вкладываю в свой собственный код.

Оказывается, я забыл добавить эту проверку

if( ![NSThread isMainThread] ){
    [self performSelectorOnMainThread:@selector(start) 
                           withObject:nil 
                        waitUntilDone:NO];
    return;
}

Это гарантирует, что метод start выполняется в главном потоке, где NSAutoreleasePool уже существует.Простая ошибка, простое решение.

...