我有一些NSOperations子类可以处理CoreData导入。我相信我已经勾选了大多数非主线程问题
main
方法NSManagedObjectContext
这些操作被加载到NSOperationQueue中,并发操作的最大数量设置为1。
该代码在iOS 4.0.1上可以完美运行,但是在iOS 3.1.3设备上,会收到很多类似以下的日志消息
*** _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
方法
最佳答案
解决了此操作,该操作使用Dave Dribin在article中的建议启动NSURLConnection。但是,在可能的情况下,我尽量不要剪切并粘贴其他人的代码,因此我始终可以过滤自己要放入自己的代码中的内容。
原来我忘了加这张支票
if( ![NSThread isMainThread] ){
[self performSelectorOnMainThread:@selector(start)
withObject:nil
waitUntilDone:NO];
return;
}
这样可以确保
start
方法在已经存在NSAutoreleasePool
的主线程上运行。简单的错误,简单的解决方案。
关于iphone - NSOperation仅在iOS 3设备上泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3833564/