ios - 使用 GCD 异步加载指向服务器上图像的本地 JSON 文件

标签 ios objective-c json grand-central-dispatch nsurl

我知道有很多关于这个主题的资源,但我的代码示例与这里的大多数示例的实现不同,我不确定如何解决这个问题。我正在尝试使用 Grand Central Dispatch 来解决它。似乎我已经尝试了所有方法,但是某些东西(我猜是正在下载的图像)阻塞了主线程。当我推送到包含 TableView 的 View Controller 时,UI 会锁定几秒钟,然后显示 TableView 。之后滚动非常慢。

我对这些基本的 iOS 内容还是很陌生,因为我倾向于专注于游戏开发。我在尝试学习。也许更有经验的人可以指出我的错误?

所有 JSON 对象都存储在 NSDictionary 中。这是名为 Data.json 的数据文件:

{
  "data" :
 [

    {
        "user" : "3",
        "username" : "John",
        "avatar_url" : "http://api.mysite.com/images/avatar3.png",
        "message" : "Bonjour?"
    },
    {
        "user_id" : "4",
        "username" : "Sam",
        "avatar_url" : "http://api.mysite.com/images/avatar4.png",
        "message" : "Yes, John."
    },
    {
        "user_id" : "2",
        "username" : "Becky",
        "avatar_url" : "http://api.mysite.com/images/avatar2.png",
        "message" : "I'm new here!"
    },
  ]
}

ChatCell.h 中加载图片的方法:

- (void)loadWithData:(Data *)data {
    self.userID = chatData.user_id;
    // Where images are called from server
    self.avatarImage.image = [UIImage imageWithData:[NSData   dataWithContentsOfURL:[NSURL URLWithString:data.avatar_url]]];
    self.usernameLabel.text = data.username;
    self.messageTextView.text = data.message;
}

TableViewController.m:

 @interface TableViewController ()
   @property (nonatomic, strong) IBOutlet UITableView *tableView;
   @property (nonatomic, strong) NSMutableArray *loadedChatData;
 @end

- (void)viewDidLoad {
   ....

   self.loadedChatData = [[NSMutableArray alloc] init];
   [self loadJSONData];
 }

 - (void)loadJSONData {
   //Here is my attempt using GCD  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

  NSString *filePath = [[NSBundle mainBundle] pathForResource:@"data" ofType:@"json"];

  NSError *error = nil;

  NSData *rawData = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:&error];

  id JSONData = [NSJSONSerialization JSONObjectWithData:rawData options:NSJSONReadingAllowFragments error:&error];

    [self.loadedChatData removeAllObjects];

  if ([JSONData isKindOfClass:[NSDictionary class]])
    {
        NSDictionary *jsonDict = (NSDictionary *)JSONData;

        NSArray *loadedArray = [jsonDict objectForKey:@"data"];

        if ([loadedArray isKindOfClass:[NSArray class]])
        {
            for (NSDictionary *chatDict in loadedArray)
            {
                  Data *data = [[Data alloc] init];
                  [data loadWithDictionary:chatDict];
                  [self.loadedChatData addObject:data];
            }
        }
    }
    // Updating UI on main queue?
    dispatch_async(dispatch_get_main_queue(), ^{
       [self.tableView reloadData];
    });
  });
}


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

   if (cell == nil) {
     NSArray *nib = [[NSBundle mainBundle] loadNibNamed:cellIdentifier owner:self options:nil];
     cell = (ChatCell *)[nib objectAtIndex:0];
   }
    // I also tried using GCD's dispatch_async(dispatch_get_main_queue) within this method here with bad results 
    Data *data = [self.loadedChatData objectAtIndex:[indexPath row]];
    [cell loadWithData:data];

    return cell;
}

最佳答案

- (void)loadWithData:(Data *)data {
    self.userID = chatData.user_id;
    // Where images are called from server
    self.usernameLabel.text = data.username;
    self.messageTextView.text = data.message;
    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    //Background Thread Functionality
    UIImage *avatarImage = [UIImage imageWithData:[NSData   dataWithContentsOfURL:[NSURL URLWithString:data.avatar_url]]];

    dispatch_async(dispatch_get_main_queue(), ^(void){
        //Run UI Updates
        self.avatarImage.image = avatarImage;
    });
});

}

关于ios - 使用 GCD 异步加载指向服务器上图像的本地 JSON 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29204716/

相关文章:

iphone - 如何确定为 Web 服务 API 实现的 Http 方法类型

sql - 如何将具有树结构的表聚合到单个嵌套 JSON 对象?

javascript - 从 json 中删除斜杠 jquery

ios - 从小部件扩展访问核心数据

javascript - 当没有互联网访问时,WKWebView 不会完成/超时

objective-c - NSPopUpButton-如何有选择地禁用某些菜单项?

ios - AVPlayer 不显示任何内容

json - 无法保存文件 : Permission denied Ubuntu

iphone - 应用程序在前台时的 UILocalNotifications

iphone - 定义了outlet,连接它们,它们都返回(null)