我正在获取所有图像的GPS信息,并将它们存储在字典中。我会将本字典中的经纬度值传递给reverseGeocodeLocation
函数调用,并将结果存储在数据库中。
这里的问题是该函数是一个异步调用,我需要同步整个过程,以便将我的记录插入表中。
例如:我的数组读取以下坐标:32.77003,96.87532。现在,它调用reverseGeocodeLocation
函数,将这些坐标作为CLLocation
对象传递。现在,在此异步功能返回我返回地理编码的位置名称之前,下一组具有新坐标集的请求将发送到reverseGeocodeLocation
函数。这导致将记录插入数据库不一致。
有什么办法可以使整个任务同步?
即让我的for循环等待reverseGeocodeLocation
返回一个值,然后继续进行下一个要进行地理编码的记录?
我的一些代码在这里:
for (int imgIdx=0; imgIdx<[imageMetaMutArray count]; imgIdx++)
{
NSDictionary *localGpsDict = [[NSDictionary alloc]initWithDictionary: [imageMetaMutArray objectAtIndex:imgIdx]];
imgLatLoc=[localGpsDict valueForKey:@"Latitude"];
imgLongLoc=[localGpsDict valueForKey:@"Longitude"];
dateStamp=[localGpsDict valueForKey:@"DateStamp"];
timeStamp=[localGpsDict valueForKey:@"TimeStamp"];
if(imgLatLoc && imgLongLoc && dateStamp && timeStamp)
{
CLGeocoder *geoCoder=[[CLGeocoder alloc]init];
CLLocation *currentLocation=[[CLLocation alloc]initWithLatitude:[imgLatLoc doubleValue] longitude:[imgLongLoc doubleValue]];
[geoCoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placeMarks, NSError *err){
if(err)
{
NSLog(@"Reverse geo-coding failed because: %@",err);
return;
}
if(placeMarks && placeMarks.count>0)
{
CLPlacemark *placeMarkers=placeMarks[0];
NSDictionary *locationDictionary=placeMarkers.addressDictionary;
NSString *country=[locationDictionary objectForKey:(NSString *)kABPersonAddressCountryKey];
NSString *city=[locationDictionary objectForKey:(NSString *)kABPersonAddressCityKey];
NSString *state=[locationDictionary objectForKey:(NSString *)kABPersonAddressStateKey];
NSLog(@"logged in from:");
if(city)
{
NSLog(@"city: %@",city);
locName = [[NSString alloc]initWithString:city];
if(state)
{
NSLog(@"state: %@",state);
locName=[locName stringByAppendingString:@","];
locName=[locName stringByAppendingString:state];
}
if(country)
{
NSLog(@"country: %@",country);
locName=[locName stringByAppendingString:@","];
locName=[locName stringByAppendingString:country];
}
}
else
{
if(state)
{
NSLog(@"state: %@",state);
locName = [[NSString alloc]initWithString:state];
if(country)
{
NSLog(@"country: %@",country);
locName=[locName stringByAppendingString:@","];
locName=[locName stringByAppendingString:country];
}
}
else
{
NSLog(@"country: %@",country);
locName = [[NSString alloc]initWithString:country];
}
}
}
else
{
NSLog(@"Placemark Error code:: %lu\n%@",(unsigned long)placeMarks.count,placeMarks);
}
[locName retain];
NSLog(@"location decoded is: %@",locName);
/*Call for Insert into Images table*/
[self insertDataImgTbl:locName];
});
}
}
}
最佳答案
简短的答案是您不能使其同步。
您想要做的是将继续下一个对象的代码移到reverseGeocodeLocation的完成块中,因为这是您可以尽快提交另一个reverseGeocodeLocation请求的代码。让我看看我是否可以在这里做一些伪代码...(也就是说,我还没有编译它,所以可能不完全正确...)
// in place of the original for loop:
[self reverseGeocodeForIndex:0];
// Doing the reverse geocode is in a method so you can easily call it from within the completion block.
// Maybe your parameter is not the imgIdx value but is instead some object -- I'm just hacking your posted code
// The point is that your completion block has to be able to tell when
// it is done and how to go on to the next object when it is not done.
(void) reverseGeocodeForIndex:(int) imgIdx {
NSDictionary *localGpsDict = [[NSDictionary alloc]initWithDictionary: [imageMetaMutArray objectAtIndex:imgIdx]];
imgLatLoc=[localGpsDict valueForKey:@"Latitude"];
imgLongLoc=[localGpsDict valueForKey:@"Longitude"];
dateStamp=[localGpsDict valueForKey:@"DateStamp"];
timeStamp=[localGpsDict valueForKey:@"TimeStamp"];
if(imgLatLoc && imgLongLoc && dateStamp && timeStamp)
{
CLGeocoder *geoCoder=[[CLGeocoder alloc]init];
CLLocation *currentLocation=[[CLLocation alloc]initWithLatitude:[imgLatLoc doubleValue] longitude:[imgLongLoc doubleValue]];
[geoCoder reverseGeocodeLocation:currentLocation completionHandler:^(NSArray *placeMarks, NSError *err){
// completion block
if(err)
{
// error stuff
}
if(placeMarks && placeMarks.count>0)
{
// what happens when you get some data
}
// now see if we are done and if not do the next object
if (imgIdx<[imageMetaMutArray count])
{
[self reverseGeocodeForIndex:imgIdx+1];
} else {
// Everything is done maybe you want to start something else
}
}];
} else {
// Since you might not reverseGeocode an object you need an else case
// here to move on to the next object.
// Maybe you could be more clever and not duplicate this code.
if (imgIdx<[imageMetaMutArray count])
{
[self reverseGeocodeForIndex:imgIdx+1];
} else {
// Everything is done maybe you want to start something else
}
}
}
而且,当然,您不能依靠此操作来做其他任何事情,除非您在对最后一个对象进行反向地理编码后可能会启动一些操作。
这种异步编程可以使您发疯。