views:

39

answers:

0

I have some NSOperations subclasses that handle CoreData imports. I believe i've ticked most of the non-main thread issues

  • I create my own autorelease pool in the main method
  • I create a NSManagedObjectContext for each operation

These operations are loaded into a NSOperationQueue, with the maximum number of concurrent operations set 1.

The code works perfectly on a iOS 4.0.1, however on a iOS 3.1.3 device a get a lot of log messages like the following

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

NSOperation Subclass main method

-(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];
}

The __lookup:inContext: method

-(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];

}

Most of the other methods instance methods, ie threadContext look similar to the __lookup:inContext: method. I'm aware that i don't create Autorelease pools for the instance methods, but according to my understanding of how autorelease works, as long as these methods are only called inside the main method, after the NSAutoreleasePool has been created, the outer most pool should be used. I create objects such as the NSManagedObjectContext lazily, and in most cases don't use the start method