我正在以 JSON 格式从服务器获取数据。它只有大约 150 条记录,我最初没有使用 GCD,但时不时地,当我点击应用程序中的按钮以查看包含数据的表格时,它会延迟大约几秒钟,然后切换到表格 View 并显示数据.所以我实现了 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];
});
});
}
最佳答案
这基本上是正确的。将数据检索分派(dispatch)到后台队列,然后将模型和 UI 更新分派(dispatch)回主队列。干得好。
就速度较慢而言,我看不出有任何原因可以解释这一点。 GCD 引入了一些开销,但通常无法观察到。这可能有点像“看着水壶永远不会沸腾”的问题。
不过,还有一些不相关的想法:
我可能建议将排序移到
for
循环之外,但在reloadData
之前。您将其排序 150 次。如果进行插入排序,您可以在循环内进行,但我认为这里不会发生这种情况。我会把排序移到循环的末尾。我不确定是否可以观察到性能提升,但应该会有一些适度的改进。您可能想确保
data
不是nil
(例如,没有网络,或其他一些网络问题),因为如果是,JSONObjectWithData
会崩溃。您的
json
对象是一个外部变量。它可能应该是您的retrieveData
方法的局部变量。无需将其设为实例变量。如果合适,将其设为局部变量会更简洁。您可能应该采用类名以大写字母开头的命名约定(例如,
Exhibitor
而不是exhibitors
)。非常小的一点,但是您的
blabel
变量可能应该是bLabel
。更好的是,我可以重命名这三个变量boothLabel
、boothName
和boothUrlString
。您正在为
exhibitorsArray
使用实例变量。我想你也在其他地方这样做。您可能需要考虑使用 declared properties相反。您可能希望在将代码分派(dispatch)到后台之前打开网络事件指示器,并在执行
reloadData
时将其关闭。[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
如果你想变得非常复杂,你可能会重新考虑是否要使用 GCD 的全局队列(因为如果你快速刷新 10 次,所有十次都会运行,而你可能只希望最后一次运行) .这是一个更复杂的话题,所以我不会在这里介绍,但如果你有兴趣,你可能想引用操作队列的讨论 Concurrency Programming Guide ,您可以在其中创建可取消的操作(因此,在启动新操作时,取消之前的操作)。
您可能还想引用 Building Concurrent User Interfaces on iOS WWDC 2012 视频。
但这与您最初的问题完全无关:是的,您已经适本地解决了这个问题。
关于ios - 我的大中央调度使用 : Am I using it correctly?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17951601/