2015-10-18 36 views
1

我有一个应用程序,当你第一次打开它,主视图获取所有的朋友和他们的个人资料图片和加载UITableView与朋友的名字,用户名和个人资料图片每个单元格。问题是,UITableView需要更长的时间来加载所有的朋友,如果你有很多朋友,例如大约30(大约需要5-8秒)。我将所有这些图像存储在与朋友的用户名相关联的字典中,以便稍后重复使用它们,但主要问题是应用程序第一次启动时要加载所有图像需要多长时间。这是我对现在的代码,做它在遍历每个朋友:iOS - 更快速的方式加载UIImages从URL的

[auth.loggedInUser getFriendsSuccessCallback:^(NSArray* friends){ 
    for (User* friend in friends) { 
     if (![weakSelf.friendImageDictionary.allKeys containsObject:friend.userName]) 
     { 
      UIImage *profilePicture; 
      if (!friend.profilePicture) { 
       profilePicture = [UIImage imageNamed:@"ProfilePic"]; 
      } 
      else 
      { 
       NSURL *profilePictureURL = [NSURL URLWithString:friend.profilePicture]; 
       NSData * profilePictureData = [NSData dataWithContentsOfURL:profilePictureURL]; 
       profilePicture = [UIImage imageWithData:profilePictureData]; 
      } 
      if (profilePicture == nil) 
      { 
       profilePicture = [UIImage imageNamed:@"ProfilePic"]; 
      } 
      [weakSelf.friendImageDictionary setObject:profilePicture forKey:friend.userName]; 
     } 
    } 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [weakSelf.tableView reloadData]; 
    }); 
} 

如何显著减少所花费的时间来加载所有这些图像的数量有什么建议?

进展情况:

好了,所以我使用AFNetworking用下面的代码:

[auth.loggedInUser getFriendsSuccessCallback:^(NSArray* friends){ 
    NSMutableArray *profilePictureRequests = [[NSMutableArray alloc] init]; 
    for (User* friend in friends) { 
     if (![weakSelf.friendImageDictionary.allKeys containsObject:friend.userName]) 
     { 
      if (!friend.profilePicture) { 
       UIImage *profilePicture = [UIImage imageNamed:@"ProfilePic"]; 
       [weakSelf.friendImageDictionary setObject:profilePicture forKey:friend.userName]; 
      } 
      else 
      { 
       NSURL *profilePictureURL = [NSURL URLWithString:friend.profilePicture]; 
       NSURLRequest *urlRequest = [NSURLRequest requestWithURL:profilePictureURL]; 
       AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest]; 
       requestOperation.responseSerializer = [AFImageResponseSerializer serializer]; 
       [requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, UIImage* profilePicture) { 
        NSLog(@"Response: %@", profilePicture); 
        if (profilePicture == nil) 
        { 
         profilePicture = [UIImage imageNamed:@"ProfilePic"]; 
        } 
        [weakSelf.friendImageDictionary setObject:profilePicture forKey:friend.userName]; 
       } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
        NSLog(@"Image error: %@", error); 
       }]; 
       [profilePictureRequests addObject:requestOperation]; 
      } 
     } 
    } 
    for (AFHTTPRequestOperation *requestOperation in profilePictureRequests) 
    { 
     [requestOperation start]; 
    } 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [weakSelf.tableView reloadData]; 
     weakSelf.dashboardViewController.loadingCoverView.hidden = YES; 
     [weakSelf.dashboardViewController.tableActivityIndicator stopAnimating]; 
     NSLog(@"FINISHED LOADING ALL PROFILE PICTURES"); 
    }); 
} 

基本上我所做的就是保存在某个NSMutableArrayAFHTTPRequestOperation对于需要加载每个图像。之后,我重复了NSMutableArray并开始每个AFHTTPRequestOperation

问题:

这只是做加载所有图像非常快,但我想我错误地做这件事。我的加载视图与我的活动指示器完成并消失之前,所有图像完成下载并添加到我的NSMutableDictionary当它应该发生后,所有的下载和添加。有没有办法让我的加载视图和活动指示器消失所有UIImage下载后台线程完成后?

另一个问题关于AFNetworking

是我做的方式(使约30个图像下载后台线程在这种情况下,在同一时间发生)不是好的做法与AFNetworking?如果一个用户拥有超过100个朋友,并且同时发生超过100个图像下载后台线程,它会导致未来的问题吗?

+0

听起来像是你应该减少图像服务器端的大小。 – vikingosegundo

+0

这已完成,并且大量图像的加载时间仍然是个问题,特别是当用户拥有更多朋友时。我认为在设置一个新的后台线程的范围内,必须从url加载每个图像。这可能吗? – Rafi

+1

使用AFNetworking和异步下载非常容易 – james

回答

3

你可能不会减少下载时间,但你可以让它看起来更快。

您正在主线程上使用同步下载,这是一个非常糟糕的主意。

有像AFNetworking这样的库可以很容易地设置异步下载。或者,如果你想自己做,你可以使用NSURLSession,或者NSURLSession(这是iOS中9弃用)

+0

我的代码片段在我的服务器的API调用块内,所以我在技术上从后台线程加载图像。我会很快更新我的代码。 – Rafi

+1

您是否确定**成功回调发生在主线程上?你可以使用NSThread isMainThread来告诉。在成功回调中添加一个像这样的调试语句:'NSLog(“isMainThread =%d”,[NSThread isMainThread]);' –

+1

您应该重构您的代码以一次加载一个图像,并在每个图像下载时更新UI 。像AFNetworking这样的框架使得这更容易。 –

0

当UIImages工作,我经常使用SDWebImage:https://github.com/rs/SDWebImage

你可以看看它的README。 md以获得更具体的细节,但它与缓存异步地添加了对来自Web的远程图像的支持。

使用它的一个例子:

#import <SDWebImage/UIImageView+WebCache.h> 

[self.imageView sd_setImageWithURL:[NSURL URLWithString:imageURL] 
+0

因此,如果我使用这个库并在for循环中包含此语句,例如,图像是否将同时在不同的线程上同时下载,或者for循环会等待图像下载,直到下一次迭代? – Rafi

+0

SDwebImage的主要用途是将图像保存在缓存中,以便从第二个缓存中加载它们,并在内存警告时清除缓存。 –