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

Load a local JSON file that points to images on a server asynchronously using GCD

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

我对这些基本的 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;
    });
});

}