【问题标题】:NSOperation(s) leaks only on iOS 3 deviceNSOperation(s) 仅在 iOS 3 设备上泄漏
【发布时间】:2010-09-30 18:16:22
【问题描述】:

我有一些处理 CoreData 导入的 NSOperations 子类。我相信我已经勾选了大部分非主线程问题

  • 我在 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: 方法。我知道我不会为实例方法创建 Autorelease 池,但根据我对 autorelease 工作原理的理解,只要这些方法仅在 main 方法内部调用,在创建 NSAutoreleasePool 之后,应使用最外层池。我懒惰地创建诸如 NSManagedObjectContext 之类的对象,并且在大多数情况下不使用start 方法

【问题讨论】:

    标签: iphone multithreading nsoperation nsoperationqueue nsautoreleasepool


    【解决方案1】:

    已解决,此操作使用 Dave Dribin 的 article 中的建议启动 NSURLConnection。但是,在可能的情况下,我尽量不要剪切和粘贴其他人的代码,所以我总是可以过滤我放入自己代码的内容。

    原来我忘了添加这张支票

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

    确保start 方法在主线程上运行,其中NSAutoreleasePool 已经存在。简单的错误,简单的解决方案。

    【讨论】:

      猜你喜欢
      • 2011-09-07
      • 2011-02-23
      • 1970-01-01
      • 2017-03-30
      • 2012-06-13
      • 2011-08-20
      • 1970-01-01
      • 2011-05-29
      • 2018-07-08
      相关资源
      最近更新 更多