【问题标题】:Received memory warning when saving data on a background thread在后台线程上保存数据时收到内存警告
【发布时间】:2013-03-08 10:10:55
【问题描述】:

我在NSMutableArray(>2500) 中有很多对象,当我保存它时,应用程序崩溃(收到内存警告 x3)。

    NSLog(@"start");
    NSInteger saveTemp = 0;
    NSData *data = [NSURLConnection sendSynchronousRequest:req returningResponse:&response error:&err];
    if ([data length] > 0 && err == nil)
    {
        MyClass* rcust;
        NSString *respStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSMutableArray* cust = [respStr JSONValue];
        for(NSDictionary *v in cust)
        {
            if([dataProvider getClassById:[[v valueForKey:@"Id"] integerValue] error:nil] == nil)
            {
                rcust = [dataProvider createClass];
                rcust.clsId = [v valueForKey:@"Id"];
            }
            else
            {
                rcust = [dataProvider getClassById:[[v valueForKey:@"Id"] integerValue] error:nil];
            }
            rcust.cstZip = [v valueForKey:@"Zip"] == [NSNull null]? @"": [v valueForKey:@"Zip"];

            saveTemp++;
            if(saveTemp > 1000)
            {
                NSLog(@"save");
               [dataProvider saveContext];
                saveTemp = 0;
            }
        }
        [dataProvider saveContext];
    }

这里是saveContext 方法

- (void)saveContext {
    NSError*err = nil;
    if(![[self managedObjectContext] save:&err])
    {
        NSLog(@"Unresolved error %@, %@", err, [err userInfo]);
    }
}

更新: 我在方法中添加了代码,然后就可以了。

2013-03-21 15:18:54.641  start
2013-03-21 15:19:31.843  save
2013-03-21 15:23:21.126  save

即数据保存速度越来越慢,过了一会儿,应用程序崩溃了。

【问题讨论】:

  • 什么时候收到内存警告?尝试发布一些其他详细信息。

标签: ios core-data memory-management crash nsmanagedobject


【解决方案1】:

所以看起来您有超过 2500 个客户从该 NSURLRequest 中返回。当您填充 cust 数组时,您已经拥有该数据的四个副本(作为 NSData、作为 NSString、作为 NSMutableArray 以及在您的 NSManagedObjectContext 中)。

使用@autoreleasepool 包装您的 NSData 和 NSString 转换。一旦你完成了你的-JSONValue 电话,你就不再需要这些陈述了。

然后,将您的处理循环也包含在 @autoreleasepool 中。这将允许释放中间结果(即使是您看不到的结果)。

最后,当您执行 saveContext 时,也对托管对象上下文执行 -reset。

给你的另外两个注意事项:

您在第 4 行中对 NSError 参数的检查不正确。对于具有 NSError** 参数的方法,如果操作成功,则 NSError 返回值未定义。逻辑应该是if (data.length > 0) 然后继续,否则检查 NSError。请参阅 NSURLConnection 的类参考。

另外,您的 getClassById 方法似乎违反了 Cocoa 命名标准。如果该方法以单词get 开头,则它必须通过参数中的引用返回其结果。见https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html#//apple_ref/doc/uid/20001282-BCIGIJJF

【讨论】:

  • 谢谢。它解决了内存泄漏的问题。但是,在一个循环中,保存的所有内容都变得越来越慢,越来越慢。如何加快数据保存过程?
  • 真的是saveContext调用很慢吗?还是其他部分?这将是启动 Instruments 并打开 com.apple.CoreData.SQLDebug(参见 useyourloaf.com/blog/2010/03/11/…)的好时机。我注意到您错误命名的getClassById:error 在某些迭代中被调用了两次。它有什么作用?
猜你喜欢
  • 1970-01-01
  • 2011-06-06
  • 2012-09-28
  • 2012-07-05
  • 1970-01-01
  • 2011-04-30
  • 1970-01-01
  • 2015-08-08
相关资源
最近更新 更多