2011-10-27 8 views
8

私はUIMapViewを表示する私のアプリケーションでモーダルビューを持っています。次に、このマップビュー(以下のコード)に多数の注釈(800以上)を追加します。MKMapView用のコードの最適化 - 多数の注釈

問題は、すべてのピンがロードされている間にユーザーが1分ほど待たなければならないことです。また、すべての800ピンが地図上にあると、アプリは低速になります。

誰でも私のコードをどのように改善することができますか?

ありがとうございます。

#import "MapView.h" 
#import "MapPlaceObject.h" 


@implementation MapView 
@synthesize mapViewLink, mapLocations, detail, failedLoad; 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
{ 
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
if (self) { 
    // Custom initialization 
} 
return self; 
} 

-(void)addPins 
{ 

for (MapPlaceObject * info in mapLocations) { 


    double latitude = info.longitude; 
    double longitude = info.latitude; 

    NSString * name = info.name; 
    NSString * addressline = info.addressOne; 
    NSString * postcode = info.postCode; 

    NSString * addresscomma = [addressline stringByAppendingString:@", "]; 
    NSString * address = [addresscomma stringByAppendingString:postcode]; 

    CLLocationCoordinate2D coordinate; 
    coordinate.latitude = latitude; 
    coordinate.longitude = longitude; 
    MyLocation *annotation = [[[MyLocation alloc] initWithName:name address:address coordinate:coordinate] autorelease]; 


    [mapViewLink addAnnotation:annotation]; 

} 
} 

- (void)showLinks : (id)sender { 


if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { 
    detail = [[DetailViewController alloc] initWithNibName:@"DetailViewController-iPad" bundle:nil]; 
} 

else if (!detail) { 

    NSLog(@"Detail is None"); 

    detail = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil]; 

} 

int uniqueID = ((UIButton *)sender).tag; 

//PlaceObject *info = [mapLocations objectAtIndex:uniqueID]; 

detail.UniqueID = uniqueID; 
detail.hidesBottomBarWhenPushed = YES; 

[self.navigationController pushViewController:detail animated:YES]; 

self.detail = nil; 

[detail release]; 

} 

- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation{ 

if (annotation == mapView.userLocation){ 
    return nil; //default to blue dot 
}  

MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"currentloc"]; 
annView.pinColor = MKPinAnnotationColorRed; 

nameSaved = annotation.title; 

for (PlaceObject * info in mapLocations) { 

    if (info.name == nameSaved) { 

     saveID = info.UniqueID; 

    } 
} 

UIButton *advertButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; 
advertButton.frame = CGRectMake(0, 0, 23, 23); 
advertButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; 
advertButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; 

[advertButton addTarget:self action:@selector(showLinks:) forControlEvents:UIControlEventTouchUpInside]; 

advertButton.tag = saveID; 

annView.rightCalloutAccessoryView = advertButton; 

annView.animatesDrop=TRUE; 
annView.canShowCallout = YES; 
annView.calloutOffset = CGPointMake(-5, 5); 
return annView; 

} 

- (void)dealloc 
{ 
[mapViewLink release]; 
[mapLocations release]; 
[detail release]; 
self.failedLoad = nil; 
[failedLoad release]; 
[super dealloc]; 
} 

- (void)didReceiveMemoryWarning 
{ 
// Releases the view if it doesn't have a superview. 
[super didReceiveMemoryWarning]; 

// Release any cached data, images, etc that aren't in use. 
} 

- (void)viewWillAppear:(BOOL)animated { 

if (firstTime) { 

    CLLocationCoordinate2D zoomLocation; 

    zoomLocation.latitude = 51.50801; 
    zoomLocation.longitude = -0.12789; 

    MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(zoomLocation, 15*METERS_PER_MILE, 15*METERS_PER_MILE); 

    MKCoordinateRegion adjustedRegion = [mapViewLink regionThatFits:viewRegion];     

    [mapViewLink setRegion:adjustedRegion animated:YES]; 

    firstTime = NO; 

}  
} 

- (void)viewDidLoad 
{ 
[super viewDidLoad]; 

firstTime = YES; 

failedLoad = [[NSMutableArray alloc]init]; 

self.mapLocations = [BluePlaqueDatabase database].mapInfo; 

[self addPins]; 
} 

- (void)viewDidUnload 
{ 
[mapViewLink release]; 
mapViewLink = nil; 
[super viewDidUnload]; 
// Release any retained subviews of the main view. 
// e.g. self.myOutlet = nil; 
} 

答えて

10

ここで行うことができる2つの最大速度の向上は、以下のとおりです。

  • は、それが新しいビューに、それも同じ場合は、アノテーションを表示する必要があるたびに作成し、今(注釈ビューの再利用を実装します
  • UniqueIDがどのように設定されているかを変更するには、現在、注釈ビューを作成するたびにすべての注釈がループされています(マップビューがズームまたはスクロールされるたびに発生する可能性があります) - 最初の時間だけではありません)

まず、代わりにviewForAnnotation方法でUniqueIDを検索し、カスタム注釈クラスMyLocationにプロパティとしてUniqueIDを追加し、注釈識別子を渡し、あなたは注釈を追加するときに、プロパティを設定するには、ボタンのタグを使用しますaddPinsで自身:

annotation.uniqueID = info.UniqueID; // <-- give id to annotation itself 
[mapViewLink addAnnotation:annotation];  

また、個別にプロパティを割り当てるのではなく、initWithNameメソッドにパラメータとしてuniqueIDを追加することができます。


次に、注釈ビューの再利用を実現するために、viewForAnnotation方法は次のようになります。ボタン押しに対応し、詳細を示すためにどのUniqueID把握するために、最後に

- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation{ 

    if (annotation == mapView.userLocation){ 
     return nil; //default to blue dot 
    }  

    NSString *reuseId = @"StandardPin"; 
    MKPinAnnotationView *annView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseId]; 
    if (annView == nil) 
    { 
     annView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId] autorelease]; 

     annView.pinColor = MKPinAnnotationColorRed; 
     annView.animatesDrop = YES; 
     annView.canShowCallout = YES; 
     annView.calloutOffset = CGPointMake(-5, 5); 

     UIButton *advertButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure]; 
     advertButton.frame = CGRectMake(0, 0, 23, 23); 
     advertButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; 
     advertButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; 

     annView.rightCalloutAccessoryView = advertButton; 
    } 
    else 
    { 
     //update the annotation property if view is being re-used... 
     annView.annotation = annotation; 
    } 

    return annView; 
} 


- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view 
      calloutAccessoryControlTapped:(UIControl *)control 
{ 
    MyLocation *myLoc = (MyLocation *)view.annotation; 

    int uniqueID = myLoc.uniqueID; 

    NSLog(@"calloutAccessoryControlTapped, uid = %d", uniqueID); 

    //create, init, and show the detail view controller here... 
} 


:について、calloutAccessoryControlTappedデリゲートメソッドを実装しますこれらの変更がすべて完了した後で、注釈の最初の読み込みだけがほとんどの時間を費やします。それでも問題が解決しない場合は、現在表示されている領域に表示されるアノテーションのみを追加し、ユーザーが表示領域を変更すると注釈を追加/削除します。

4

私はアンナと完全に同意します。しかし、同時に800のAnnotationViewsが極端な遅れたインターフェースになると考えてください。したがって、マップがスクロールやズームなどのユーザーのやりとりを提供する必要がある場合は、アノテーションビューのいくつかの種類のクラスタリングを実装することをお勧めします。