2014-11-06 31 views
0

我創建了一個從URL下載圖像的類UITableViewCells(在這個項目中,我不能使用SDWebImageView或來自互聯網的其他代碼),但它看起來像使用了大量的內存,我的tableview不是加載如此之快。任何人都可以指出什麼是問題?UITableView中使用太多內存的圖像

代碼:

//MyHelper class  
+(NSString *)pathForImage:(NSString *)urlImageString{ 
    if ([urlImageString class] == [NSNull class] || [urlImageString isEqualToString:@"<null>"] || [urlImageString isEqualToString:@""]) { 
     return @""; 
    } 
    NSArray *pathsInString = [urlImageString componentsSeparatedByString:@"/"]; 

    NSString *eventCodeString = [pathsInString objectAtIndex:[pathsInString count] - 2]; 
    NSString *imageNameString = [pathsInString lastObject]; 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); 
    NSString *cachePath = [paths objectAtIndex:0]; 

    cachePath = [MyHelper validateString:[cachePath stringByAppendingString:eventCodeString]]; 
    [cachePath stringByAppendingString:@"/"]; 

    return [cachePath stringByAppendingString:imageNameString]; 
} 

+(BOOL)imageExistsForURL:(NSString *)urlString{ 

    if (!([urlString class] == [NSNull class])) 

    { 
     NSString *filePath = [MyHelper pathForImage:urlString]; 
     NSFileManager *fileManager = [NSFileManager defaultManager]; 

     return [fileManager fileExistsAtPath:filePath]; 
    } 

    return false; 
} 

+(void)setAsyncImage:(UIImageView *)imageView forDownloadImage:(NSString *)urlString{ 
    CGRect activityFrame = CGRectMake(0, 0, 60, 60); 
    UIActivityIndicatorView *activity = [[UIActivityIndicatorView alloc] initWithFrame:activityFrame]; 
    activity.layer.cornerRadius = activity.frame.size.width/2; 
    activity.clipsToBounds = YES; 

    activity.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray; 
    [imageView addSubview:activity]; 
    [activity startAnimating]; 
    dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_async(concurrentQueue, ^{ 

     NSData *image; 
     if ([urlString class] == [NSNull class]) { 
      image = nil; 
     } else { 
      image = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:urlString]]; 
     } 

     dispatch_async(dispatch_get_main_queue(), ^{ 
      [activity stopAnimating]; 
      [activity removeFromSuperview]; 
      if (image) 
      { 
       [UIView animateWithDuration:0.9 animations:^{ 
        imageView.alpha = 0; 
        imageView.image = [UIImage imageWithData:image]; 
        imageView.alpha = 1; 
       }]; 
      NSString *filePath = [MyHelper pathForImage:urlString]; 
      NSError *error; 
      [image writeToFile:filePath options:NSDataWritingAtomic error:&error]; 

      } 
      else 
      { 
       imageView.image = [UIImage imageNamed:@"icn_male.png"]; 
      } 
     }); 
    }); 
} 

+(NSString *)validateString:(NSString *)string{ 
    if (string == (id)[NSNull null] || string.length == 0) 
     return @""; 

    return string; 
} 

+ (UIImage*)imageWithImage:(UIImage*)image 
       scaledToSize:(CGSize)newSize; 
{ 
    float proportion; 
    if (image.size.height > image.size.width) { 
     proportion = image.size.height/newSize.height; 
    } else { 
     proportion = image.size.width/newSize.width; 
    } 

    UIGraphicsBeginImageContext(newSize); 
    [image drawInRect:CGRectMake(newSize.width - (image.size.width/proportion), 
           newSize.height/2 - (image.size.height/proportion)/2, 
           image.size.width/proportion, 
           image.size.height/proportion)]; 
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    return newImage; 
} 

使用此代碼:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSString *cellIdentifier = @"MyCell"; 
    MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath]; 


    if ([MyHelper imageExistsForURL:photoURLString ]) { 
     UIImage *image = [UIImage imageWithContentsOfFile:[MyHelper pathForImage:photoURLString]]; 
     eventImageView.image = [MyHelper imageWithImage:image scaledToSize:CGSizeMake(60, 60)]; 
    } else { 
     [MyHelper setAsyncImage:eventImageView forDownloadImage:photoURLString ]; 
    } 
} 
+0

我建議使用工具來分析你的應用程序。顯然,如果您的圖像是1000x1000像素,並且自動調整大小以適應100x100圖像視圖,那麼這就是您的問題。 – dandan78 2014-11-06 12:57:36

+0

是的,我使用了配置文件,我有像你說的情況。這種情況最好的辦法是什麼?還有其他更好的方法嗎? – Claudio 2014-11-06 12:59:44

回答

1

因爲它是現在很清楚,你正在使用超大圖像,解決的辦法是要弄清楚你的形象有多大需要在爲了在你的應用中看起來很好。

根據您可以更改系統的服務器端部分的程度,有幾種操作方法。

  • 使用最適合最高分辨率情況(3x)的圖像,並讓2x和1x設備進行縮放。這又浪費了一點。

  • 創建一些方案,您將能夠爲您的設備類型(可能通過追加2倍,3倍等)獲得適當大小的圖像到圖像文件名稱。可以說是最好的選擇。

  • 請在客戶端調整大小。這可能有點CPU密集型,可能是我認爲最糟糕的方法,因爲你會不必要地做很多工作。但是,如果您無法更改服務器的工作方式,那麼這是您唯一的選擇。

與您的代碼的另一個問題是,你正在做的主/ UI線程的窗口大小,這是阻止你的用戶界面,這是一個禁忌。切勿在主線上執行長時間操作。

你應該在後臺線程上使用dispatch_async或者NSOperation和一個順序隊列來減少內存使用量。請注意,這可能會造成新的問題,因爲您必須在圖像準備就緒時更新圖像視圖,並考慮諸如單元格是否仍然可見等情況。我偶然發現了一篇很好的博客文章,所以我建議您搜索網頁。

但是,如果圖像真的很大,那麼也許你可以考慮設置一個代理服務器,然後從那裏獲取調整大小的圖像,而不是主服務器。當然,在這種情況下,你將不得不考慮知識產權問題。

+0

我的問題是:我無法調整服務器端的圖像大小。在客戶端大小。有沒有其他方式來調整大小,而不是使用我使用的代碼? – Claudio 2014-11-06 13:21:08