0

这是我正在使用的代码片段。我有一个模型叫x_locator. 当我对模型进行多线程处理时,maps.google.com 返回 620 错​​误(请求太多太快),但是当我将模型留在主线程上时,它工作正常......只有在发出请求时 UI 被锁定.

-(CLLocationCoordinate2D) getLocationFromAddressString:(NSString*) addressStr {
    NSString *urlStr = [NSString stringWithFormat:@"http://maps.google.com/maps/geo?    q=%@&output=csv", 
                       [addressStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
    NSString *locationStr = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlStr]];
    NSArray *items = [locationStr componentsSeparatedByString:@","];

    double lat = 0.0;
    double lon = 0.0;

    if([items count] >= 4 && [[items objectAtIndex:0] isEqualToString:@"200"]) {
        lat = [[items objectAtIndex:2] doubleValue];
        lon = [[items objectAtIndex:3] doubleValue];
    }
    else {
        NSLog(@"Address, %@ not found: Error %@",addressStr, [items objectAtIndex:0]);
    }
    CLLocationCoordinate2D location;
    location.latitude = lat;
    location.longitude = lon;

    return location;
}

编辑:这是我尝试使用 GCD 的方式......这是在我的 ViewController 中

- (void)viewDidLoad
{
    [super viewDidLoad];

    //set any delegates
    self.locationManager.delegate = self;
    [locationManager startUpdatingLocation];
    fuelMapView.showsUserLocation = YES;

    [self setInitialRegion];
    locationManager.distanceFilter = 100;

    //create the model
    x_locator = [[Locator alloc]init];
    x_locator.delegate = self;

    dispatch_queue_t finder = dispatch_queue_create("Locator", NULL);
    //if I do this, only some of the locations are found. If I leave it on the main thread, all locations are found.
    dispatch_async(finder, ^{
    [x_locator getUsersZipUsingLocation:[locationManager location]];
     });
}

所做getUsersZipUsingLocation:的只是使用反向地理编码获取用户的邮政编码,然后它调用另一个方法来检索地址数组(根据用户的邮政编码),最后每个地址都使用转换为坐标位置-(CLLocationCoordinate2D) getLocationFromAddressString:(NSString*) addressStr

编辑2:我很犹豫是否要完整发布代码,因为人们可能会失去对问题的关注并继续判断我的编码是否优雅......

无论如何...在调用该方法之前-(CLLocationCoordinate2D) getLocationFromAddressString:(NSString*) addressStr,我必须将地址组合成可以作为变量传递的形式addressStr。地址是分块到达的,所以我组装这些部分,然后继续从 url 获取数据......

NSString *urlStr = [NSString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@&output=csv",
                    [addressStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

数据返回后,我说[NSThread sleepForTimeInterval:0.05];并接受下一个请求。

感谢您的评论和时间:)

4

1 回答 1

2

首先,getLocationFromAddressString:不应以get;为前缀 尝试downloadretrieve忽略它(约定)。

其次,发布有关您如何实际使呼叫并发的详细信息。你提出了多少要求?

“请求太多太快”听起来非常准确;您需要限制在远程服务器上发送请求的速度。

我过去曾使用信号量来限制并发性。

打开多个文件的大中央策略


所有 getUsersZipUsingLocation: 所做的是使用反向地理编码获取用户的邮政编码,然后它调用另一个检索地址数组的方法(根据用户的邮政编码),最后使用 -(CLLocationCoordinate2D) 将每个地址转换为坐标位置getLocationFromAddressString:(NSString*) addressStr

通过以下方式调用它:

dispatch_async(finder, ^{
[x_locator getUsersZipUsingLocation:[locationManager location]];
 });

首先,您现在有一个异步调用来加载该信息。因此,“只找到一些”项目也就不足为奇了。一旦转向异步,就必须使用某种通知机制来指示加载何时完成

假设这usersZipUsingLocation:是同步的,您可以:

dispatch_async(finder, ^{
[x_locator getUsersZipUsingLocation:[locationManager location]];
[self yoManILoadedTheGoodsDealWithTheUpdate];
 });

但这仍然不能解释你的 620。那个 620 表示你正在同时(或几乎如此)发出一堆请求。上述任何一项都没有声称的 50 毫秒延迟。

所以……这个故事似乎还有更多内容!:)


仍然不清楚您为什么要达到 API 请求限制。

你真的不应该使用睡眠机制来延迟这些事情。相反,如果绝对必要,可以结合使用类似信号量的模式来控制同时进行的飞行请求的数量(最好使用系统的异步加载 API)以及基于计时器的延迟。这会将所有与延迟相关的东西都推到系统上,而没有保证的线程契约(根据睡眠线程的要求)。

于 2013-01-22T00:29:41.777 回答