如何在iOS中从服务器异步获取数据并在收到数据后更新UI?

How to fetch data asynchronously from server in iOS and update UI after receiving data?

在我的 iOS 应用程序中,我试图从服务器获取数据。我想异步执行此操作。我正在尝试这个:

 - (void)loadData {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

  /** code for fetching data. **/

  dispatch_async(dispatch_get_main_queue(), ^{
    myList = [NSMutableArray arrayWithObjects:fetchedData, nil];
  });
 });


}

上述方法 loadData() 是从 tableViewController 的 init() 方法调用的。

我正在使用此列表中对象的数据显示为单元格。 但是在我从服务器接收数据之前,主线程尝试从列表中填充 UI (这显然是空的)。我如何同步这些?

我发现:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 

上面的函数(returnsmyList的计数)returns0,因此我的table显示为空。在我从服务器接收数据之前调用此函数(因为这需要更多时间,而此方法会立即在主线程中转移控制)。

我建议你检查一下 AFNetworking(https://github.com/AFNetworking/AFNetworking)。在 AFHTTPRequestOperationManager 的完成处理程序中,只需设置您的 tableView dataSourcedelegates 以及 reloadData()。另一种方法是在 tableView dataSource setter 方法中重新加载数据。

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSString *stringURL = //ur url;

[manager GET:stringURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    if (completion) {
        //ur completion
    }
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    if (completion) {
        NSLog(@"error: %@", [error localizedDescription]);
    }
}];

从服务器获取数据后,只需再次 'reload' 您的 table。然后 再次调用方法(numberOfRows、numberOfSections、...)。

Call this method to reload all the data that is used to construct the table, including cells, section headers and footers, index arrays, and so on. For efficiency, the table view redisplays only those rows that are visible. It adjusts offsets if the table shrinks as a result of the reload. The table view’s delegate or data source calls this method when it wants the table view to completely reload its data. It should not be called in the methods that insert or delete rows, especially within an animation block implemented with calls to beginUpdates and endUpdates.

检查 https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/index.html#//apple_ref/occ/instm/UITableView/reloadData

 - (void)loadData {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

      /** code for fetching data. **/

      dispatch_async(dispatch_get_main_queue(), ^{
        myList = [NSMutableArray arrayWithObjects:fetchedData, nil];
        yourTable.reloadData()  // <-- reload your table after update myList
      });
     });


    }
- (void)loadData {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

/** code for fetching data. **/

  dispatch_async(dispatch_get_main_queue(), ^{
    myList = [NSMutableArray arrayWithObjects:fetchedData, nil];
    [yourTable reloadData]; // reload the data

  });
 });


}

您可能想在调用您的 fetch 函数后尝试调用您的 loadData 函数。在你的场景中,loadData 在你获取函数之前首先被调用,这就是为什么你总是得到一个空的 myList。在调用 loadData 之前先调用 fetch 函数。

如果你想使用 async,你也可以将你的 fetch 函数放在你的 async 中,但放置一个断点,这样它就不会总是调用它。