我从数据库中提取地址列表。列表的大小可以是0-n。但是n通常是50-60。
我正在尝试发现最佳方式,将所有这些位置添加到地图视图中。
我目前使用的方法如下。
我创建了一个mutableArray(注释)来保存我的所有注释(我删除并经常添加它们,所以最好保留它们以便快速添加/删除)。
我运行我加载的地址列表(来自DB)将地址传递给反向地理编码器以获取lat和long。
检查lat和long是否为0,0(意味着我受谷歌限制)。
Y - 如果是这样,我会标记有禁止加价并将@“”添加到注释数组中。在添加和删除时,必须保留注释以便正确引用。
N - 如果没有,那么我将该注释添加到地图和注释数组中。
如果有禁率,我会通过注释数组查找@“”,当找到一个时,继续执行步骤2-5。
我递归调用此函数(步骤5),直到添加所有注释。但似乎效率低下。
是否有人发现了一种更有时间和内存效率的方法?
这是初始调用启动注释加载:
- (void)addLocations {
/*
Setup an array to hold all annotations, this is done for fast removal/addition when filtering which happens often. So far, through testings, has shown to be the optimal way.
*/
annotations = [[NSMutableArray alloc] init];
bool needsReload = NO;
//Loop through all locations parsed from the DB
for (int i = 0; i < [[[[self appDelegate] rssParser]rssItems] count]; i++) {
NSString *temp = [NSString stringWithFormat:@"%@, %@, %@", [[[[[self appDelegate]rssParser]rssItems] objectAtIndex:i] Address], [[[[[self appDelegate] rssParser]rssItems]objectAtIndex:i]City], [[[[[self appDelegate] rssParser]rssItems]objectAtIndex:i]State]];
CLLocationCoordinate2D tempLocation = [self addressLocation:temp];
if (tempLocation.latitude == 0.0) {
//We have been rate banned and flag for a re-run through locations.
[[[[[self appDelegate] rssParser]rssItems]objectAtIndex:i] setLocation:nil];
needsReload = YES;
[annotations addObject:@""];
} else {
/*
Set location of property. Done for property use in other locations of app.
*/
CLLocation *tempLoc = [[CLLocation alloc] initWithLatitude:tempLocation.latitude longitude:tempLocation.longitude];
[[[[[self appDelegate] rssParser]rssItems]objectAtIndex:i] setLocation:tempLoc];
//Create new annotation with proper coordinates
MapAnnotation *addAnnotation = [[MapAnnotation alloc] initWithCoordinate:tempLocation];
addAnnotation.name = [[[[[self appDelegate] rssParser]rssItems]objectAtIndex:i]Address];
// Check to see if location has an image associated with it.
if ([[[[[[self appDelegate] rssParser]rssItems]objectAtIndex:i] imageURLs] count] > 0 )
addAnnotation.thumbURL = [[[[[[self appDelegate] rssParser]rssItems]objectAtIndex:i] imageURLs] objectAtIndex:0];
else
addAnnotation.thumbURL = nil;
addAnnotation.tag = i;
addAnnotation.description = [NSString stringWithFormat:@"%@, %@ | $%@",[[[[[self appDelegate] rssParser]rssItems]objectAtIndex:i]City] , [[[[[self appDelegate] rssParser]rssItems]objectAtIndex:i]State] ,[[[[[[self appDelegate]rssParser]rssItems] objectAtIndex:i] Deposit] stringByReplacingOccurrencesOfString:@".00" withString:@""]];
//Add annotation to "annotations" array for fast addition/removal when filtering.
[annotations addObject:addAnnotation];
[self._mapView addAnnotation:addAnnotation];
//Doesn't seem necessary in ARC but somehow helps with memory on iPhone 3GS
temp = nil;
addAnnotation = nil;
}
}
//Attempt to force a refresh so annotations show up.
[self._mapView setCenterCoordinate:self._mapView.centerCoordinate zoomLevel:ZOOM_LEVEL animated:NO];
/*
If there was a rate ban we need to run through the locations again to get proper coordinates
*/
if (needsReload == YES) {
//Sleep the thread to shake off rate ban from google.
[NSThread sleepForTimeInterval:2.0f];
//Move to the background so user can begin interacting with app
[self performSelectorInBackground:@selector(rateLimited) withObject:nil];
} else {
//All locations were property loaded so we can stop here.
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
self.radiusControl.hidden = NO;
}
}
如果有禁率,我们会移动到这个以递归方式调用方法来正确获取所有坐标。
- (void)rateLimited {
/*
Create an array to hold the newly loaded annotations. For some reason the map will only load annoations if I add this this way. Instead of adding them one at a time as done before. I suppose it has to do with some refresh issue.
*/
NSMutableArray *tempReload = [[NSMutableArray alloc] init];
bool needsReload = NO;
/*
Run through the parsed list of property objects again looking for @""
*/
for ( int i = 0; i < [annotations count]; i++) {
if ([[annotations objectAtIndex:i] isEqualToString:@""]) {
Property *tempProp = (Property*) [[[self.appDelegate rssParser] rssItems] objectAtIndex:i];
NSString *temp = [NSString stringWithFormat:@"%@, %@, %@", [tempProp Address], [tempProp City], [tempProp State]];
CLLocationCoordinate2D tempLocation = [self addressLocation:temp];
//There was another rate ban so we need to run through list again.
if (tempLocation.latitude == 0.0) {
needsReload = YES;
} else {
CLLocation *tempLoc = [[CLLocation alloc] initWithLatitude:tempLocation.latitude longitude:tempLocation.longitude];
[[[[[self appDelegate] rssParser]rssItems]objectAtIndex:i] setLocation:tempLoc];
MapAnnotation *addAnnotation = [[MapAnnotation alloc] initWithCoordinate:tempLocation];
addAnnotation.name = [tempProp Address];
if ([[tempProp imageURLs] count] > 0 )
addAnnotation.thumbURL = [[tempProp imageURLs] objectAtIndex:0];
else
addAnnotation.thumbURL = nil;
//Have to keep tags corresponding to the inital listLocation assigned when DB is parsed from server. Done so when properties are added/removed they can be referenced correctly.
addAnnotation.tag = [tempProp listLocation];
//Set description
addAnnotation.description = [NSString stringWithFormat:@"%@, %@ | $%@",[tempProp City] , [tempProp State] ,[[tempProp Deposit] stringByReplacingOccurrencesOfString:@".00" withString:@""]];
//Repace the @"" with the proper annotation.
[annotations replaceObjectAtIndex:i withObject:addAnnotation];
//Add annotation for bulk addition after loop as finished.
[tempReload addObject:addAnnotation];
temp = nil;
addAnnotation = nil;
}
}
}
//Bulk add new annoations
[self._mapView addAnnotations:tempReload];
//If we need to reload, we recusivly call this method until all locations have proper coordinates.
if (needsReload == YES){
needsReload = NO;
tempReload = nil;
//The recusive call
[self rateLimited];
} else {
//All locations have property loaded now we can finish. *wew*
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
self.radiusControl.hidden = NO;
}
}
这是我的反向地理编码方法,也许有人可能有更好的方法来实现它。
-(CLLocationCoordinate2D)addressLocation:(NSString*)_address {
NSString *urlString = [NSString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@&output=csv",
[_address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSError* error = nil;
NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString ] encoding:NSASCIIStringEncoding error:&error];
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");
}
CLLocationCoordinate2D location;
location.latitude = latitude;
location.longitude = longitude;
return location;
}
答案 0 :(得分:0)
我会将每个位置设置为自己的对象,然后让该对象自己负责找出并设置自己的位置。 (如果出现问题,请在稍有延迟后重试)
然后你可以根据需要创建它们并让它们完成它们的工作 - 只有在它们让你知道它们准备好后才会在地图上显示它们。