我從數據庫中提取地址列表。列表的大小可以是0-n。但是,n通常是50-60。將註釋添加到MKMapView的最佳方法
我試圖發現最佳方式將所有這些位置添加到地圖視圖。
,我目前使用的方法去如下。
我創建了一個mutableArray(註釋)持有我所有的註釋(我刪除和添加他們經常回來,所以最好讓他們所有手頭上快速添加/刪除)。
我通過我傳遞地址到反向地理編碼,以獲得lat和長地址(從DB)的加載列表運行。看到
檢查lat和長是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;
}