简体   繁体   中英

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

I know that there are a lot of resources on SO about this subject, but my code example is a different implementation than most of the examples here and I'm not sure how to solve this. I'm trying to use Grand Central Dispatch to solve it. It seems I've tried everything, but something (my guess the images being downloaded) are blocking the main thread. When I push to my view controller containing the table view, the UI locks up for a few seconds then it displays table view. After that scrolling is very slow.

I'm still pretty new to this basic iOS stuff, because I tend to focus on game development. I am trying to learn. Maybe someone more experienced can point out my mistake?

All JSON objects are being stored into a NSDictionary. Here is the data file called 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!"
    },
  ]
}

The method in ChatCell.h that loads the images:

- (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;
    });
});

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM