2011-05-13 88 views
4

我的问题是关于核心数据和内存使用情况。我之前使用过核心数据,但这次数据量更高,这让我意识到还有很多事情要知道。我看到有几个其他类似的帖子,我从他们那里得到了有趣的信息,但是在应用之后,我的应用程序仍然崩溃。我一直在处理这个问题一个星期。有人请帮忙。核心数据 - 内存使用情况:我的应用程序崩溃

基本上,我有三个后续类似的64,15和17迭代循环分别。他们在模拟器上工作得很好。在几个iPad上测试,他们得到了内存警告,并且在相同的迭代中(第一个循环的数字34)崩溃。在iPad 2上测试它会在第二个循环的第14号时崩溃。仪器显示在现场和整体上存储器使用量约为1.5 MB。有几个KB泄漏。

毛圈执行以下(下面的代码)

  • 执行与核心数据
  • 对于每一个记录中的取取存储为行属性属性(字符串)
  • 呼叫的过程的参数,其采用该参数并返回数据(大约数百KB)
  • 将这些数据存储在同一行的另一个属性属性(可变形)中

很常见的任务不是吗?现在

,因为我到内存的问题,我试图用我掌握的所有已知的(由我)的工具,它们是:

  • 释放资尽快对象
  • 创建自动释放池和排水他们尽快不属于自己的对象
  • 保存方面尽快
  • 转物体进入故障尽快

applyi后所有这些技巧我都得到了一个令人兴奋的结果:应用程序崩溃的地方和以前完全相同。

这是它的代码。

- (void) myMainProcedure { 
    [self performLoop1]; 
    [self performLoop2]; // Similar to loop1 
    [self performLoop3]; // Similar to loop1 
} 
- (void) performLoop1 { 
    NSError * error = nil; 
    NSAutoreleasePool * myOuterPool; 
    NSAutoreleasePool * myInnerPool; 

    NSManagedObjectContext * applicationContext = [[[UIApplication sharedApplication] delegate] managedObjectContext]; 
    [applicationContext setUndoManager:nil]; 


    NSEntityDescription * myEntityDescription = [NSEntityDescription entityForName:@"EntityName" 
               inManagedObjectContext:applicationContext]; 
    NSFetchRequest * myFetchRequest = [[NSFetchRequest alloc] init]; 
    [myFetchRequest setEntity:myEntityDescription]; 

    NSString * column = @"columnName"; 
    NSPredicate * aWhereClause = [NSPredicate predicateWithFormat: 
            @"(%K = %@)", column, [NSNumber numberWithInt:0]]; 
    [myFetchRequest setPredicate: aWhereClause]; 

    myOuterPool = [[NSAutoreleasePool alloc] init]; 
    NSArray * myRowsArray = [applicationContext executeFetchRequest:myFetchRequest                  
                   error:&error]; 
    NSMutableArray * myRowsMutableArray = [[NSMutableArray alloc] initWithCapacity:0]; 
    [myRowsMutableArray addObjectsFromArray: myRowsArray]; 
    [myOuterPool drain]; 
    [myFetchRequest release]; 

    EntityName * myEntityRow; 
    int totalNumberOfRows = [myRowsMutableArray count]; 

    myOuterPool = [[NSAutoreleasePool alloc] init]; 
    for (int i = 0; i < totalNumberOfRows; i++) { 

      myInnerPool = [[NSAutoreleasePool alloc] init]; 
      myEntityRow = [myRowsMutableArray objectAtIndex:0]; 
      NSString * storedSmallAttribute = myEntityRow.smallAttribute; 
      UIImageView * largeData = [self myMethodUsingParameter: smallAttribute]; 
      myEntityRow.largeAttribute = largeData; 
      [myRowsMutableArray removeObjectAtIndex:0]; 

      [applicationContext save:&error]; 
      [applicationContext refreshObject:myEntityRow mergeChanges:NO]; 
      [myInnerPool drain]; 
      [largeData release]; 
    } 
    [myOuterPool drain]; 
    [myRowsMutableArray release]; 
} 

- (UIImageView *) myMethodUsingParameter : (NSString *) link { 
    UIImageView * toBeReturned = nil; 
    NSURL *pdfURL = [NSURL fileURLWithPath:link]; 
    CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((CFURLRef)pdfURL); 
    CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1); 
    CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox); 
    UIGraphicsBeginImageContext(pageRect.size); 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0); 
    CGContextFillRect(context,pageRect); 
    CGContextSaveGState(context); 
    CGContextTranslateCTM(context, 0.0, pageRect.size.height); 
    CGContextScaleCTM(context, 1, - 1); 
    CGContextSetInterpolationQuality(context, kCGInterpolationHigh); 
    CGContextSetRenderingIntent(context, kCGRenderingIntentDefault); 
    CGContextDrawPDFPage(context, page); 
    CGContextRestoreGState(context); 
    UIImage *imageToBeReturned = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    CFRelease(pdf); 
    toBeReturned = [[UIImageView alloc] initWithImage:imageToBeReturned]; 
    UIGraphicsEndImageContext(); 
    return toBeReturned; 
} 
  • 请注意,

    • 的可变数组被引入作为一个(显然没用)策略,以 有对象发布了相同的策略的越早
    • 池已添加广告的一部分
    • 关于插值质量的声明是唯一一个改善 的情况(比如移动崩溃 向前迈进了一点点)
    • 保留计数管理对象内的周期为6〜10 (?)我知道,RC是不是有价值 资料,但仍,我做了一个试验 ,我发现我在将此应用程序强制为 崩溃之前,可能会将 多个发布消息发送到托管的 对象。但重点是, 我不应该释放一个 对象我不拥有,是吗? ...
    • 设置请求的实体也获得了一些 与 的其他实体的双向关系,但仍然是这个 有关吗?

谢谢。

+0

为什么你要返回并存储UIImageView而不是图像? – Hagelin 2011-05-13 13:46:00

回答

0

我认为你应该重新看看你的问题。 处理核心数据的方法有很多,比您的方法简单得多。 为Core Data实体创建类文件可能会对您有所帮助。 另外,当您保存文件时,您应该认真评估每个对象的必要性以及是否可以采用更好的方法。 在你的情况,我会提供两个建议:


对于每个PDF网址,

  • a.Assign的唯一标识符。
  • b。在您的 核心数据存储区中存储此唯一标识符。
  • c.Add网址为 后台进程的队列创建
    您的PDF(后台进程将
    允许用户继续工作,而正在生成 的PDF文件。你
    可以在
    更新您的委托 进度或创建一个临时图像 被替换时,PDF是
    创建)
  • d.Save使用 唯一标识符为NA在您的应用程序 目录(或照片库中的图片)我。
  • e。当需要时,将图像从 磁盘加载到UIImageView或
    任何适当的。

对于每个PDF网址,

  • a.Draw的PDF。
  • b.Get的UIImage表示
  • c.Convert到PNG NSData的 (UIImagePNGRepresentation(图像))
  • d.Save NSData的在CoreData。
  • e.Load NSData并在需要时转换为UIImage 。
+0

谢谢你的回答。我认为你是对的,我需要重新审视这一点,但我似乎没有找到方法。 – user236739 2011-05-15 14:45:10

+0

谢谢你的回答。我认为你是对的,我需要重新审视这一点,但我似乎没有找到方法。顺便说一下,第一个建议听起来不错,即使我没有多线程经验。第二个建议或多或少是我想要做的,即使没有转换到NSData。现在让我们假设选择第二种方法。我们需要从核心数据中获取一些记录,然后更新每个记录,在一个属性中设置一个大的NSData。如何安排这个循环来防止内存问题?你可以发布任何代码或代码? – user236739 2011-05-15 14:53:03

+0

我认为可以真正帮助你的是阅读Core Data上的一些很好的基础材料。您需要了解Core Data如何分配和存储信息,以及如何检索信息等。以下是一个很好的教程,帮助您开始: – 2011-05-16 13:07:42

相关问题