iOS中的内存管理,Simulator vs idevice给出了不同的结果

时间:2014-06-06 11:13:45

标签: ios iphone memory-management ios7

我正在从服务器下载图片,这是我的代码。

-(void) DownloadImages
{
   NSLog(@"Images count to download %lu",(unsigned long)[productID count]); // about 3000
   if ([productID count] > 0)
   {
       // Document Directory
       NSString *myDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
       for (i = 0; i < [productID count]; i++)
       {
       @autoreleasepool      // is this right of use autoreleasepool???
       {
           @autoreleasepool      
           {
               [self performSelectorInBackground:@selector(UpdateUI) withObject:nil];
           }
           NSLog(@"image no %d", i);
          NSString *imageURL = [NSString stringWithFormat:@"http://serverPath/%@/OnlineSale/images/products/%@img.jpg",clientSite,[productID objectAtIndex:i]];
           UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]];
           // Reference path
           NSString *imagePath = [NSString stringWithFormat:@"%@/%@img.jpg",myDirectory,[productID objectAtIndex:i]];
          NSData *imageData = [NSData dataWithData:UIImageJPEGRepresentation(image, 1.0f)];
          [imageData writeToFile:imagePath atomically:YES];   
        }
     }
      NSLog(@"Downloading images completed...");
  }

}

编辑:这是UpdateUI方法

 -(void) UpdateUI
 {
    spinner.hidden = NO;
[spinner startAnimating];
    progressCounter.hidden = NO;
    status.text = @"Synchronising Product Images...";
    progressCounter.text = [NSString stringWithFormat:@"%d / %lu", i,(unsigned long)[productID count]];
 }

处理时,当我在模拟器时,使用的最大内存为: 超过1500张图片下载。

enter image description here

但是在iPad上进行测试,最大内存达到 106.9 MB ,应用程序因此消息崩溃,刚刚下载500张图片后:

enter image description here

并且屏幕显示以下消息: enter image description here

在过去的两天里,我抓住了这一点,抓住了我的头后,没有找到任何解决方案。请帮我解决这个问题..

修改 使用autoreleasedpool的方式是对还是???

2 个答案:

答案 0 :(得分:2)

首先,我建议在@autoreleasepool内部包含整个for循环块。它看起来像这样:

   for (i = 0; i < [productID count]; i++)
   {
     @autoreleasepool      // is this right of use autoreleasepool???
     {
        [self performSelectorInBackground:@selector(UpdateUI) withObject:nil];
         NSLog(@"image no %d", i);
         NSString *imageURL = [NSString stringWithFormat:@"http://serverPath/%@/OnlineSale/images/products/%@img.jpg",clientSite,[productID objectAtIndex:i]];
         UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]];
         // Reference path
         NSString *imagePath = [NSString stringWithFormat:@"%@/%@img.jpg",myDirectory,[productID objectAtIndex:i]];
         NSData *imageData = [NSData dataWithData:UIImageJPEGRepresentation(image, 1.0f)];
         [imageData writeToFile:imagePath atomically:YES];   
      }
   }

如果您尝试使用@autoreleasepool块完成的操作是处理updateUI中分配的内存,那么这不是正确的方法。您应该将updateUI正文括在@autoreleasepool内。

我还建议发布updateUI的内容;你甚至可以评论那个叫出来,看看下载是否会导致内存问题。

更一般地说,我在后台线程上更新UI似乎很可疑。作为一般做法,UI应仅在主线程上更新。 (但是没有看到updateUI定义,我真的不能说这是否合适。)

关于使用设备或模拟器获得的不同结果,这是“正常”。当涉及内存处理时,模拟器完全不可靠,您还可以使用模拟器检测设备上没有的泄漏。

编辑:

作为一个简单的补丁,尝试这种方法:

for (i = 0; i < [productID count]; i++)
   {
      dispatch_async(dispatch_get_main_queue(), ^{

        [self UpdateUI];

         NSLog(@"image no %d", i);
        NSString *imageURL = [NSString stringWithFormat:@"http://serverPath/%@/OnlineSale/images/products/%@img.jpg",clientSite,[productID objectAtIndex:i]];
         UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]];
         // Reference path
         NSString *imagePath = [NSString stringWithFormat:@"%@/%@img.jpg",myDirectory,[productID objectAtIndex:i]];
        NSData *imageData = [NSData dataWithData:UIImageJPEGRepresentation(image, 1.0f)];
        [imageData writeToFile:imagePath atomically:YES];   
      });
 }

正如您将注意到的那样,我将单独调度循环中的每个步骤。通过这种方式,邮件循环将能够更新UI。请注意,此实现不是最佳的,因为dataWithContentsOfURL将需要一些执行(因为它需要网络访问)并且不应该在主线程上执行(但是你已经这样做了)。这应该在后台队列上发送。

答案 1 :(得分:0)

您应该使用更合适的方法来获取图像数据。 我建议你试试NSURLDownload课程。

或者,您可以使用流行的第三方网络框架之一,例如AFNetworking