3

我正在从服务器获取 JSON 格式的数据。它只有大约 150 条记录,我最初并没有使用 GCD,但是当我时不时地点击应用程序中的按钮以查看包含数据的表格时,它会延迟大约几秒钟,然后切换到表格视图并显示数据. 所以我实现了 GCD,现在当我点击按钮时,它会立即切换到 tableview,但是加载数据会有几秒钟的延迟,这似乎比 GCD 之前的实现要长。所以我不确定我是否正确使用了 GCD,或者是我的服务器导致了延迟(我认为这是罪魁祸首)。这是 GCD 在名为 retrieveData 的方法中的实现,我在 viewDidLoad 中将其称为 [self retrieveData]:

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

        NSURL *url = [NSURL URLWithString:@"http://MY_URL/JSON/document.json"];
        NSData * data = [NSData dataWithContentsOfURL:url];

        dispatch_async(dispatch_get_main_queue(), ^{

    json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];

    //Set up our exhibitors array
    exhibitorsArray = [[NSMutableArray alloc] init];

    for (int i = 0; i < json.count; i++) {
        //create exhibitors object
        NSString * blabel = [[json objectAtIndex:i] objectForKey:@"BoothLabel"];
        NSString * bName = [[json objectAtIndex:i] objectForKey:@"Name"];
        NSString * bURL = [[json objectAtIndex:i] objectForKey:@"HyperLnkFldVal"];


        exhibitors * myExhibitors = [[exhibitors alloc] initWithBoothName: bName   andboothLabel: blabel andBoothURL: bURL];

        //Add our exhibitors object to our exhibitorsArray
        [exhibitorsArray addObject:myExhibitors];

        //Sort by name
        NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
        [exhibitorsArray sortUsingDescriptors:[NSMutableArray arrayWithObject:sort]];

    }

    [self.myTableView reloadData];

        });
    });

}
4

1 回答 1

5

这基本上是正确的。将数据检索分派到后台队列,然后将模型和 UI 更新分派回主队列。做得好。

就速度较慢而言,我看不出有什么可以解释的。GCD 引入了一些开销,但通常是不可观察的。这可能是一个“看着水壶永远不会沸腾”的问题。

不过,有一些不相关的想法:

  1. 我可能会建议将排序移到for循环之外,但在reloadData. 您正在对其进行 150 次排序。如果进行插入排序,您可以在循环内进行,但我认为这里不会发生这种情况。我会将排序移到循环的末尾。我不确定性能提升是否可以观察到,但应该会有一些适度的改进。

  2. 您可能需要确定data不是nil(例如没有网络,或其他一些网络问题),因为如果是,JSONObjectWithData将会崩溃。

  3. 您的json对象是一个外部变量。它可能应该是您retrieveData方法的局部变量。无需将其设为实例变量。如果合适,将其设为局部变量会更简洁。

  4. 您可能应该采用类名以大写字母开头的命名约定(例如Exhibitor,而不是exhibitors)。

  5. 非常次要的一点,但您的blabel变量可能应该是bLabel. 更好的是,我可能会重命名这三个变量boothLabelboothNameboothUrlString

  6. 您正在为exhibitorsArray. 我想你也在其他地方这样做。您可能要考虑使用声明的属性

  7. 您可能希望在将代码分派到后台之前打开网络活动指示器,并在执行时将其关闭reloadData

    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
    
  8. 如果您想变得更加复杂,您可能会重新考虑是否要使用 GCD 的全局队列(因为如果您快速刷新 10 次,所有十次都会运行,而您可能只希望运行最后一个)。这是一个更复杂的话题,所以我不会在这里讨论,但如果你有兴趣,你可能想参考并发编程指南中关于操作队列的讨论,你可以在其中创建可取消的操作(和因此,在启动新操作时,取消之前的操作)。

    您可能还想参考Building Concurrent User Interfaces on iOS WWDC 2012 视频。

但这与您最初的问题无关:是的,您已经适当地解决了这个问题。

于 2013-07-30T15:54:44.523 回答