1

我正在尝试在我的表格视图中加入盛大的中央调度。我有一个财产:NSArray *topPlaces

topPlacesis 是来自 Flickr 查询的字典数组。这需要一些时间来执行,所以我想把它放在一个单独的线程上。此表用于topPlaces填写表的每一行(注意:此表是应用程序加载时出现的第一个视图)。因为有几个方法调用了 getTopPlaces,所以如果 topPlaces 没有初始化,我会在 getTopPlaces 中进行延迟实例化。我的代码目前:

- (NSArray *)getTopPlaces
{

   if (!_topPlaces)
      {
        dispatch_queue_t downloadrQueue = dispatch_queue_create("lister downloader", NULL);
        dispatch_async(downloadrQueue, ^{
            _topPlaces = [FlickrFetcher topPlaces];

            dispatch_async(dispatch_get_main_queue(), ^{
                NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"_content" ascending:YES];

                NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
                NSArray *flickrTopPlacesAlphabetic = [_topPlaces sortedArrayUsingDescriptors:sortDescriptors];

                _topPlaces = flickrTopPlacesAlphabetic;
            });
        });
        dispatch_release(downloadrQueue);
      }

   return _topPlaces;
}

The main problem I'm trying to solve is that when a row is selected, it segues to a new table view. 但是当我选择一行时,它会冻结几秒钟,直到新表加载。我希望用户即使在选择行并准备继续时也能够滚动。任何帮助将不胜感激。

4

3 回答 3

2

您可能会发现此示例项目很有帮助:https ://github.com/akosma/async-uitableview/

于 2012-07-24T01:13:50.587 回答
1

为了像@Jacob建议的那样更有效地实现这一点,您可以执行以下操作(将 your_table_view_object 替换为实际对象的引用):

- (void)updateTopPlaces
{

   if (!_topPlaces)
      {
        dispatch_queue_t downloadrQueue = dispatch_queue_create("lister downloader", NULL);
        dispatch_async(downloadrQueue, ^{
            _topPlaces = [FlickrFetcher topPlaces];


            NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"_content" ascending:YES];

            NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
            NSArray *flickrTopPlacesAlphabetic = [_topPlaces sortedArrayUsingDescriptors:sortDescriptors];

            _topPlaces = flickrTopPlacesAlphabetic;
            dispatch_async(dispatch_get_main_queue(), ^{
                [your_table_view_object reloadData];
            });
        });
        dispatch_release(downloadrQueue);
      }
}

为了完成他的建议,您将创建一个 dispatch_queue_t 类型的实例变量,并从此函数中删除调度队列的创建和释放。对于这方面的更具体的帮助,我们需要查看整个类的实现。

于 2012-07-25T08:55:27.023 回答
1

首先,以 get 开头的命名方法违反了Apple 的编码准则。以 get 开头的命名方法很少见。

您的主要问题是您正在异步调度任务以填充 _topPlaces 并在异步调用填充它之前返回它。你可以用 dispatch_sync 替换它,但是你会失去在 GCD 后台队列上处理的任何性能增益。相反,试试这个:

  1. 不要从此方法返回任何内容(void)
  2. 将您的排序向上移动到 downloadrQueue 块中(无需跳回主线程 - 排序代价高昂)
  3. 在您的主队列块中,在您的表视图上调用 reloadData
  4. 在 cellForRowAtIndexPath 中,根据 topPlaces 填充表格

您的第二个问题是,当您应该坚持使用队列时,您正在创建和销毁队列。尝试将 downloadrQueue 存储为属性并在表的视图控制器的生命周期内保留它。

于 2012-07-24T02:34:42.330 回答