Q:

Refreshing the contents of a UITableView freezes the app

I have a problem when refreshing my data in my UITableview. Currently have a UIRefreshControl that when triggered (by pulling down), executes the following:
- (void)refreshByScrolling:(UIRefreshControl *)refreshControl {
    [self refreshPriceInformation];
    [refreshControl endRefreshing];
}

At this point the UI freezes (expect for the spinning refreshControl, until the  [self refreshPriceInformation] method is completed. 
Is there anyway to make it the UI won't freeze when I'm refreshing the data? For example, on the twitter and Instagram apps you can pull down to refresh and right after start scrolling down on the table.
The code for the  [self refreshPriceInformation] is below
-(void)refreshPriceInformation
{

isRefreshing = true;

//Creating Queues for Concurrent refreshes
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);

dispatch_apply([watchedSkinList count], queue, ^(size_t i) {

        SkinToWatch *watchedSkin =[watchedSkinList objectAtIndex:i];
        [watchedSkin refreshPriceInformation];

});

 dispatch_async(queue, ^{
     NSLog(@"Saving Data to Phone");

     // resaving data to phone
     NSData *newdata = [NSKeyedArchiver archivedDataWithRootObject:watchedSkinList];
     [[NSUserDefaults standardUserDefaults] setObject:newdata forKey:@"watchSkinsArray"];
     [[NSUserDefaults standardUserDefaults]synchronize ];

    isRefreshing = false;
     [self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];

     //Updating Refresh Label
     [self updateDateAndSaveDurning:false];

 });

}

Thanks!
EDIT******
As HackerInHeels has stated below, wrapping dispatch_apply with DISPATCH_QUEUE_PRIORITY_BACKGROUND has stopped the UI from freezing! 
Follow up questions:
1)how do I make sure that this is block of code is executed last?
dispatch_async(queue, ^{
         NSLog(@"Saving Data to Phone");

//rest of code...
});

Before implementing the solution, it was the last block to execute. After the solution, that's no longer the case. Do I put in it another queue? Make it sync rather than aysnc?
Thanks again!

A:

Can you try this for me..
Wrap SkinToWatch code within dispatch_async
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    dispatch_apply([watchedSkinList count], queue, ^(size_t i) {

    SkinToWatch *watchedSkin =[watchedSkinList objectAtIndex:i];
    [watchedSkin refreshPriceInformation];

    });
});

