AFNetworking 3异步图像下载队列

时间:2016-05-19 20:42:25

标签: ios objective-c image asynchronous afnetworking

我使用AFNetworking进行与服务器的所有通信,所有内容都放在一个名为“APIConnector'”的单独类中。

我试图下载用户。当我有用户ID时,我可以生成一个URL,但我不知道在收到之前我从服务器获得了哪些用户。我现在的代码看起来像这样:

AFHTTPSessionManager *httpManager = [AFHTTPSessionManager manager];
AFHTTPSessionManager *imageManager = [AFHTTPSessionManager manager]; //Used for posting to the server
    [httpManager POST:url parameters:dict progress:nil
              success:^(NSURLSessionDataTask  * _Nonnull task, id  _Nullable responseObject) {
                  UIImageView *imageHolder = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"placeholder"]];
                  if (isUser) {
                      NSMutableArray *users = [NSMutableArray new];
                      int i = 1;
                      for (id userResult in responseObject) {
                          User *user = [[User alloc] initWithId:[userResult valueForKey:@"index"] name:[userResult valueForKey:@"name"]];
                          user.imageURL = [NSString stringWithFormat:@"%@/image/?index=%@&imgIndex=0",backendURL,user.userID];
                          [users addObject:user];
                          if (i == [responseObject count]) {
                              success(users);
                          }
                          i++;
                      }

我已经做了一些迭代改变了一些事情,尝试过这样的事情并且也喜欢这样但是有了操作:

AFHTTPSessionManager *imageManager = [AFHTTPSessionManager manager]; //Used for posting to the server
    [httpManager POST:url parameters:dict progress:nil
              success:^(NSURLSessionDataTask  * _Nonnull task, id  _Nullable responseObject) {
                  UIImageView *imageHolder = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"placeholder"]];
                  if (isUser) {
                      NSMutableArray *users = [NSMutableArray new];
                      int i = 1;
                      for (id userResult in responseObject) {
                          User *user = [[User alloc] initWithId:[userResult valueForKey:@"index"] name:[userResult valueForKey:@"name"]];
                          user.imageURL = [NSString stringWithFormat:@"url to image"];
                          [users addObject:user];
                          if (i == [responseObject count]) {
                              success(users);
                          }
                          i++;
                      }
                      NSMutableArray *usersWithImage = [NSMutableArray new];
                      for (int i = 0; i < users.count;i++) {
                          User *userImg = [users objectAtIndex:i];
                          NSString *imageURL = [NSString stringWithFormat:@"%@/image/?index=%@&imgIndex=0",backendURL,userImg.userID];
                          imageManager.responseSerializer = [AFImageResponseSerializer serializer];
                          [imageManager GET:imageURL parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable imgResponse) {
                              User *user = userImg;[users objectAtIndex:i];
                              user.profilePic.image = imgResponse;
                              [usersWithImage addObject:user];

                              if (i == users.count-1) {
                                  success(usersWithImage);
                              }
                          } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                              NSLog(@"Error: %@",error);
                          }];

它&#39;&#39;&#39;&#39;&#39;&#39;但它只是加载最后一张图像作为所有图像,我也试过:https://github.com/robertmryan/AFHTTPSessionOperation/相同的结果

EDIT / ADD:

NSMutableArray *users = [NSMutableArray new];
dispatch_group_t group = dispatch_group_create();
for (id acResult in responseObject) {
  User *user = [[User alloc]initWithId:[acResult valueForKey:@"index"] name:[acResult valueForKey:@"name"]];
  NSString *imageURL = [NSString stringWithFormat:@"%@/image/?index=%@&imgIndex=0",backendURL,user.userID];
  dispatch_group_enter(group);
  [imageManager GET:imageURL parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    user.imageData = UIImageJPEGRepresentation(responseObject, 1);
    [users addObject:user];
    dispatch_group_leave(group);     // leave if successful
    } 
failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    NSLog(@"Error: %@",error);
    dispatch_group_leave(group);     // leave if not
    }];
}

dispatch_group_notify(group,dispatch_get_main_queue(),^ {   成功(活动); //从未调用过 }); 此外,我可以控制有多少用户到达(每次通话只有10个),但我不知道他们有哪个ID。

1 个答案:

答案 0 :(得分:4)

在你的第二个例子中,你有:

if (i == users.count-1) {
    success(usersWithImage);
}

您应该使用调度组或NSOperation包装器来确定何时完成所有下载,例如:

imageManager.responseSerializer = [AFImageResponseSerializer serializer]; // you only have to do this once

NSMutableArray *usersWithImage = [NSMutableArray new];

dispatch_group_t group = dispatch_group_create();

for (User *user in users) {
    NSString *imageURL = [NSString stringWithFormat:@"%@/image/?index=%@&imgIndex=0", backendURL, user.userID];
    dispatch_group_enter(group);
    [imageManager GET:imageURL parameters:nil progress:nil success:^(NSURLSessionDataTask *task, id imgResponse) {
        user.profilePic.image = imgResponse;   // this line is worrying, though: What are you doing here
        [usersWithImage addObject:user];
        dispatch_group_leave(group);           // leave if successful
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"Error: %@",error);
        dispatch_group_leave(group);           // leave if not
    }];
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    success(usersWithImage);
});
但是,我必须承认,我发现user.profilePic.image的提法有点令人担忧。这是UIKit参考吗?你不应该在模型对象中拥有UIKit控件。

作为一个更广泛的问题,如果您不知道可能要检索的用户数量,那么下载所有图像可能不是明智地使用内存和网络资源。如果有100个用户怎么办?下载100个用户的列表将很快,但下载100个图像不会。通常,您只需将图片网址保存在模型中,但不要在图片需要之前请求图片(并且只下载所需的图片,例如,如果只有12行可见,则只下载这12张图片)。如果您搜索&#34; [ios]延迟加载图片&#34;,您可能会在此主题上找到很多讨论。

就个人而言,鉴于您已经在使用AFNetworking,我倾向于使用UIImageView+AFNetworking类别(位于UIKit+AFNetworking文件夹中)。这是一种非常优雅的方法,可以对UIImageView中的UITableViewCell进行延迟异步图像检索。