使用 Google 地理编码的 For 循环 - 高错误率 - iPhone
我使用下面的代码通过地理编码获取位置信息,然后将地图图钉添加到 Google 地图视图。该代码使用 For 循环来循环访问数据库中的每个位置。问题是代码运行时无法返回大约 50% 地点的位置信息。这些失败的项目将按照以下代码保存在 failedLoad 数组中。
谁能建议这是为什么?另外,由于这些失败的项目保存在“failedLoad”数组中,有没有办法我可以使用这个数组来加载任何丢失的引脚?
编辑
失败的项目是由于 620 错误造成的,这意味着我提交项目的速度太快。如何在代码中添加延迟?
谢谢 !
-(void)displayPlaces {
for (PlaceObject *info in mapLocations) {
// GET ANNOTATION INFOS
NSString * addressOne = info.addressOne;
NSString * name = info.name;
NSString * postCode = info.postCode;
NSString * addressTwo = [addressOne stringByAppendingString:@",London,"];
NSString * address = [addressTwo stringByAppendingString:postCode];
NSString* urlString = [NSString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@&output=csv", [address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURL* url = [NSURL URLWithString:urlString];
NSURLRequest* req = [NSURLRequest requestWithURL:url];
OHURLLoader* loader = [OHURLLoader URLLoaderWithRequest:req];
[loader startRequestWithCompletion:^(NSData* receivedData, NSInteger httpStatusCode) {
NSString* locationString = loader.receivedString;
NSArray *listItems = [locationString componentsSeparatedByString:@","];
double latitude = 0.0;
double longitude = 0.0;
if([listItems count] >= 4 && [[listItems objectAtIndex:0] isEqualToString:@"200"]) {
latitude = [[listItems objectAtIndex:2] doubleValue];
longitude = [[listItems objectAtIndex:3] doubleValue];
}
else {
NSLog(@"Error %@",name);
[failedLoad addObject : info];
}
CLLocationCoordinate2D coordinate;
coordinate.latitude = latitude;
coordinate.longitude = longitude;
MyLocation *annotation = [[[MyLocation alloc] initWithName:name address:address coordinate:coordinate] autorelease];
[mapViewLink addAnnotation:annotation];
} errorHandler:^(NSError *error) {
NSLog(@"Error while downloading %@: %@",url,error);
}];
}
}
I am using the below code to fetch location information via Geocoding and then add a map pin to a Google Map View. The code uses a For loop to cycle through each place in my database. The problem is that the code fails to return location info for about 50% of the places when run. These failed items are saved in the failedLoad array as per the code below.
Can anyone suggest why this is ? Also since these failed items are saved in the "failedLoad" array, is there a way I could use this array to load any missing pins ?
EDIT
The failed items are due to a 620 error which means that I am submitting items too quickly. How can I add a delay into the code ?
Thanks !
-(void)displayPlaces {
for (PlaceObject *info in mapLocations) {
// GET ANNOTATION INFOS
NSString * addressOne = info.addressOne;
NSString * name = info.name;
NSString * postCode = info.postCode;
NSString * addressTwo = [addressOne stringByAppendingString:@",London,"];
NSString * address = [addressTwo stringByAppendingString:postCode];
NSString* urlString = [NSString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@&output=csv", [address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURL* url = [NSURL URLWithString:urlString];
NSURLRequest* req = [NSURLRequest requestWithURL:url];
OHURLLoader* loader = [OHURLLoader URLLoaderWithRequest:req];
[loader startRequestWithCompletion:^(NSData* receivedData, NSInteger httpStatusCode) {
NSString* locationString = loader.receivedString;
NSArray *listItems = [locationString componentsSeparatedByString:@","];
double latitude = 0.0;
double longitude = 0.0;
if([listItems count] >= 4 && [[listItems objectAtIndex:0] isEqualToString:@"200"]) {
latitude = [[listItems objectAtIndex:2] doubleValue];
longitude = [[listItems objectAtIndex:3] doubleValue];
}
else {
NSLog(@"Error %@",name);
[failedLoad addObject : info];
}
CLLocationCoordinate2D coordinate;
coordinate.latitude = latitude;
coordinate.longitude = longitude;
MyLocation *annotation = [[[MyLocation alloc] initWithName:name address:address coordinate:coordinate] autorelease];
[mapViewLink addAnnotation:annotation];
} errorHandler:^(NSError *error) {
NSLog(@"Error while downloading %@: %@",url,error);
}];
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可能应该一个接一个地发送它们(或者 5 × 5?),而不是使用 for 循环并同时发送所有请求,
这是一种方法(未在实际代码中进行测试,只是我一边打字,所以可能有一些拼写错误):
当然,不要忘记在完成后(或在
dealloc
中)将属性设置回 nil 以释放内存。在情况 (1) 中,我在完成块和错误块中调用
performSelector:withObject:afterDelay
,以便只有在第一个请求/解码过程完成后才会调用下一个请求/解码过程。这样你的请求就有点序列化了。在情况(2)(注释/禁用)中,我在
startRequestWithCompletion:...
方法之后调用performSelector:withObject:afterDelay
,因此它不会等待第一个请求结束后弹出下一个请求。但你会(希望)等待足够长的时间,这样你就不会达到 GoogleAPI 速率限制请注意,这不是唯一的解决方案,还有很多其他可能性。一种是使用 NSOperationQueue 将请求一个接一个地放入队列中,并向其添加依赖项,或者在 GCD 串行队列上安排请求的发送过程(是的,我知道我告诉过你不使用 GCD 来实际发送您的请求,但这仍然适用,仍然不使用 GCD+同步请求,但您可以使用 GCD 对将调用
[OHURLLoader 的块进行排队startRequestWithCompletion:...]
在主线程上一个接一个地执行请求本身仍然由 RunLoop 在主线程上执行)Instead of using a for loop and send all your requests at the same time, you probably should send them one after the other (or 5 by 5?)
Here is one way to do it (not tested in real code, just typed as I go so may have some typo):
Of course, dont forget to set the property back to nil when done (or in the
dealloc
) to release the memory.In case (1), I call
performSelector:withObject:afterDelay
in both the completion and error blocks, so that the next request/decoding process is called only once the first has finished. This way your requests are somewhat serialized.In case (2) (commented/disabled), I call
performSelector:withObject:afterDelay
right after thestartRequestWithCompletion:...
method, so it won't wait for the end of the first request to pop the next one. But you will wait (hopefully) long enough so that you won't reach the GoogleAPI rate limitNote that this is not the only solution, there are plenty other possibilities. One being to use
NSOperationQueue
to queue the requests one after the other on a queue and add dependencies to it, or schedule the sending process of the requests on a GCD serial queue (yeah, I know I told you not to use GCD to actually send your requests, but that still apply, still dont use GCD+synchronous requests, but you can use GCD to queue blocks that will call[OHURLLoader startRequestWithCompletion:...]
on the main thread one after the other; the request itself still being executed on the main thread by the RunLoop)