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