当SearchDisplayController从webservice填充数据时,如何防止竞争条件

时间:2014-07-06 11:51:07

标签: ios web-services

当我从Web服务填充搜索数组数据时,有时会收到NSRangeException。在我的示例中,每次从搜索框中键入数据时,我都会重新加载搜索显示控制器表。然后将搜索条目发送到foursquare搜索api,一旦检索到数据,我就会更新我的搜索数组数据模型。

这是它的工作原理:

 - (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    [self searchVenuesFromFoursquare:searchString];
    return YES;
}

在上述方法中,每次用户在搜索框中输入值时都会调用委托。然后重新加载搜索表。与此同时,我对Foursquare的网络服务调用正试图检索与搜索词匹配的场地。

- (void)searchVenuesFromFoursquare:(NSString *)searchTerm
{
  void(^completionBlock)(NSArray *obj, NSError *err) =
    ^(NSArray *obj, NSError *err)
    {
    dispatch_async(dispatch_get_main_queue(), ^{
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        self.searchVenues = obj;
        [self.searchDisplayController.searchResultsTableView reloadData];
    });
};

[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
if (self.deviceLocation) {
    NSString *latLon = [NSString stringWithFormat:@"%g,%g", self.deviceLocation.coordinate.latitude, self.deviceLocation.coordinate.longitude];
    [[MakanKakiStore sharedStore]searchVenues:completionBlock withSearchTerm:searchTerm andDeviceLatLng:latLon];
}
else{
    [[MakanKakiStore sharedStore]searchVenues:completionBlock withSearchTerm:searchTerm andDeviceLatLng:nil];
  }
}

这部分似乎出现了问题。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (tableView == self.searchDisplayController.searchResultsTableView) {
    VenueSearchTableViewCell *searchVenueCell = [tableView dequeueReusableCellWithIdentifier:@"VenueSearchTableViewCell" forIndexPath:indexPath];
    [searchVenueCell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];

        NSDictionary *venueDict = [self.searchVenues objectAtIndex:indexPath.row];
        searchVenueCell.venueName.text = venueDict[@"name"];
        return searchVenueCell;
   }
}

当cellForRow尝试从searchVenues数组中检索venueDict时,我认为当模型因Web服务调用而突然改变时,可能会发生范围异常。此问题很难复制,因为它取决于Web服务响应速度和用户输入。

我现在的临时解决方法是添加此支票

if (indexPath.row + 1 <= self.searchVenues.count) {
    NSDictionary *venueDict = [self.searchVenues objectAtIndex:indexPath.row];
}

这似乎是目前最好的解决方案,可以防止范围异常问题。但是,我想知道是否有解决这个问题的最佳做法? UISearchDisplayController上的大多数教程似乎都在处理在本地初始化而不是远程Web服务器的数据。

因此,如果在为UISearchDisplayController填充数据时有最佳实践方法,有人可以建议我,我真的很感激。

非常感谢你。

1 个答案:

答案 0 :(得分:-1)

看看this answer,它很可能会解决您的所有问题。您基本上会限制对Foursquare Web服务的请求。代码:

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
    static NSTimer *timer;
    [timer invalidate];
    timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(searchVenuesFromFoursquare:) userInfo:@{@"searchString": searchString} repeats:NO];
    return NO;
}

- (void)searchVenuesFromFoursquare:(NSTimer *)timer
{
    NSString *searchString = timer.userInfo[@"searchString"];
    ...
}

对Web服务或数据存储的请求应尽可能不频繁地进行,同时达到预期目标。