2012-02-28 60 views
1

我從數據庫中提取地址列表。列表的大小可以是0-n。但是,n通常是50-60。將註釋添加到MKMapView的最佳方法

我試圖發現最佳方式將所有這些位置添加到地圖視圖。

,我目前使用的方法去如下。

  1. 我創建了一個mutableArray(註釋)持有我所有的註釋(我刪除和添加他們經常回來,所以最好讓他們所有手頭上快速添加/刪除)。

  2. 我通過我傳遞地址到反向地理編碼,以獲得lat和長地址(從DB)的加載列表運行。看到

  3. 檢查lat和長是0,0(意思是我率谷歌限制)。

  4. Y -如果是這樣,我標記已經有一個速率禁止,並將@「」添加到註釋數組中。添加和刪​​除時,必須保留註釋以便正確參考。

  5. N -如果不是那麼我將該註釋添加到地圖和註釋數組。

  6. 如果已經存在一個速度的禁令,我通過註釋陣列運行尋找@「」時,如果發現一個,用步驟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

我會設置每個位置作爲自己的對象,然後只是讓該對象本身負責找出並設置自己的位置。 (和一個小的延遲之後重試,如果有一個問題)

然後,你可以創建他們根據需要,讓他們做他們的事 - 只有你的地圖上顯示,一旦他們讓你知道他們準備好了。