Detail Disclosure Indicator MKMap to Custom View Controller - iphone

EXTRA CODE ADDED
I am new to xcode. I have managed to create annotations on my map in various different colours. What I would like to do is have each annotation lead to somewhere new with a disclosure button. I have implemented a right arrow disclosure button now what I need to know is how I link that up so that each annotation will lead to a different view controller of my choice. Here is my current code on my MapViewController implementation.
MainMapViewController.m
#import "MainMapViewController.h"
#import "LocationAnnotation.h"
#interface MainMapViewController ()
#end
//Totnes Main Centre Coordinates
#define Totnes_LATITUDE 50.433741
#define Totnes_LONGITUDE -3.685797
//The Dartmouth Inn Coordinates
#define DARTMOUTH_INN_LATITUDE 50.430036;
#define DARTMOUTH_INN_LONGITUDE -3.683873;
//Pub Offers Co-Ordinates
#define TheKingBill_LATITUDE 50.431379
#define TheKingBill_LONGITUDE -3.685495
#define TheSevenStars_LATITUDE 50.431045
#define TheSevenStars_LONGITUDE -3.682945
#define TheLordNelson_LATITUDE 50.430931
#define TheLordNelson_LONGITUDE -3.683644
//Span
#define THE_SPAN 0.01f;
#implementation MainMapViewController
#synthesize mainMapView;
- (void)viewDidLoad
{
[super viewDidLoad];
//Set Delegate
mainMapView.delegate = self;
//Create the region
MKCoordinateRegion myRegion;
//Centre
CLLocationCoordinate2D centre;
centre.latitude = Totnes_LATITUDE;
centre.longitude = Totnes_LONGITUDE;
//Span
MKCoordinateSpan span;
span.latitudeDelta = THE_SPAN;
span.longitudeDelta = THE_SPAN;
myRegion.center = centre;
myRegion.span = span;
//Set The Map View
[mainMapView setRegion:myRegion animated:YES];
//Annotation
NSMutableArray * locations = [[NSMutableArray alloc] init];
LocationAnnotation * myAnn;
//The King Bill Annotation
myAnn = [[LocationAnnotation alloc] initWithTitle:#"The King Bill"
andSubtitle:#"Another Pub In Town"
andCoordinate:CLLocationCoordinate2DMake(TheKingBill_LATITUDE, TheKingBill_LONGITUDE)
andID:1];
[locations addObject:myAnn];
//The Seven Stars Annotations
myAnn = [[LocationAnnotation alloc] initWithTitle:#"The Royal Seven Stars Hotel"
andSubtitle:#"Hotel In Town"
andCoordinate:CLLocationCoordinate2DMake(TheSevenStars_LATITUDE, TheSevenStars_LONGITUDE)
andID:2];
[locations addObject:myAnn];
//The Lord Nelson Annotations
myAnn = [[LocationAnnotation alloc] initWithTitle:#"The Lord Nelson"
andSubtitle:#"Great Pub In Centre of Town"
andCoordinate:CLLocationCoordinate2DMake(TheLordNelson_LATITUDE, TheLordNelson_LONGITUDE)
andID:3];
[locations addObject:myAnn];
[self.mainMapView addAnnotations:locations];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - MKMapViewDelegate
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation {
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
MKPinAnnotationView *annView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"pin"];
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annView.rightCalloutAccessoryView = rightButton;
int annId = ((LocationAnnotation *)annotation).idNumber;
annView.pinColor = (annId == 1) ? MKPinAnnotationColorPurple
: (annId == 2) ? MKPinAnnotationColorGreen
: MKPinAnnotationColorRed;
annView.canShowCallout = YES;
return annView;
}
#end

set rightbutton's tag to annID.
rightButton.tag = annId;
and then assign Selector to touchup event:
[rightButton addTarget:self action:#selector(YourMethod:) forControlEvents:UIControlEventTouchUpInside];
In YourMethod, you can use senders tag for navigating to different view
-(void)YourMethod:(UIButton*)sender
{
if(sender.tag==1)
{
//push viewcontroller1
}
else
{
//push viewcontroller
}
return;
}

As you can see, your right button is of type UIButton. Because of this fact you can addTarget to it:
[rightButton addTarget:self action:#selector(YourMethod) forControlEvents:UIControlEventTouchUpInside];
After user tap on rightButton YourMethod will be launched.
So for every pin you can add different button with different method, in the same way you are setting AnnotationColor
int annId = ((LocationAnnotation *)annotation).idNumber;
if (annId == 1)
{
annView.pinColor = MKPinAnnotationColorPurple;
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annView.rightCalloutAccessoryView = rightButton;
[rightButton addTarget:self action:#selector(MethodWhereYouWillFireYouNewViewController) forControlEvents:UIControlEventTouchUpInside];
}
else if (annId == 2)
{
//similar as above
}

Check This:
-(void)clickOnMapAnnotation:(UIButton*)sender
{
int AnnotationClicked =sender.tag;
if(AnnotationClicked ==1)
{
//PushViewcontroller1
}
else
{
//PushViewcontroller1
}
}
(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id ) annotation {
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
MKPinAnnotationView *annView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"pin"];
int annId = ((LocationAnnotation *)annotation).idNumber;
annView.pinColor = (annId == 1) ? MKPinAnnotationColorPurple
: (annId == 2) ? MKPinAnnotationColorGreen
: MKPinAnnotationColorRed;
//The Detail Disclosure button that I want to lead to a new view controller.
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(clickOnMapAnnotation:) forControlEvents:UIControlEventTouchUpInside];
rightButton.tag = annId;
annView.rightCalloutAccessoryView = rightButton;
annView.canShowCallout = YES;
return annView;
}

Related

MapView MKAnnotation not showing callout on MKMapView

I'm displaying a few map pins on a map view. I can't figure out why the callout won't show when an annotation is touched. Here's my code. I have some conditional code in the viewDidLoad method to display a different pin image depending on a category id. The custom pins display correctly, but when you touch them nothing happens.
thanks for any help with this.
- (void)viewDidLoad {
[super viewDidLoad];
[self requestData];
CLLocationCoordinate2D centerCoord = CLLocationCoordinate2DMake(44.2632, 11.4403);
MKCoordinateSpan span;
span.latitudeDelta=5;
span.longitudeDelta=5;
MKCoordinateRegion ITRegion = MKCoordinateRegionMake(centerCoord, span);
ITRegion.span=span;
[mapView setRegion: ITRegion animated: YES];
mapView.delegate=self;
[self.mapView setShowsUserLocation:YES];
for (int i=0; i<[publicDataArray count]; i++) {
MKPointAnnotation* annotation= [MKPointAnnotation new];
CLLocationCoordinate2D coordinate;
coordinate.latitude = [[[[publicDataArray objectAtIndex:i] objectForKey:#"address"] objectForKey:#"lat"] doubleValue];
coordinate.longitude = [[[[publicDataArray objectAtIndex:i] objectForKey:#"address"] objectForKey:#"lng"] doubleValue];
NSString *catId = [NSString stringWithFormat:#"%#",[[publicDataArray objectAtIndex:i] objectForKey:#"category_id"]];
if ([catId isEqual: #"213"]) {
annView.image = [UIImage imageNamed:#"comprareMap.png"];//sets image for pin
} else if ([catId isEqual:#"217"]) {
annView.image = [UIImage imageNamed:#"vedereMap.png"];//sets image for pin
} else if ([catId isEqual:#"221"]) {
annView.image = [UIImage imageNamed:#"mangiareMap.png"];//sets image for pin
}
annotation.coordinate = coordinate;
[mapView addAnnotation: annotation];
}
}
- (MKAnnotationView *) mapView:(MKMapView *)mapingView viewForAnnotation:(id <MKAnnotation>) annotation {
annView = nil;
if(annotation != mapingView.userLocation)
{
static NSString *defaultPinID = #"";
annView = (MKAnnotationView *)[mapingView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( annView == nil )
annView = [[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID] ;
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
annView.rightCalloutAccessoryView = rightButton;
annView.canShowCallout = YES;
}
return annView;
}

click on button in MKAnnotationView

I m working on an app using MKMapView
there's some annotation and when u click on the annotation image , details are shown
for that i ve build my custom #interface Annotation : NSObject and added a boolean value "bClicked"
now I want the user to be able to click on a detail button inside the detailview but the code i ve made is not working :
#pragma mark - MKMapViewDelegate
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
MKAnnotationView *annotationView = nil;
int index = 0;
BOOL bFound = FALSE;
for (int i=0;i<[shopAnnotations count];i++)
{
if (annotation == [shopAnnotations objectAtIndex:i])
{
index = i;
bFound = TRUE;
break;
}
}
if (bFound==FALSE)
{
//ADLog(#"bFound FALSE annotation %p",annotation);
return annotationView; // <-- nil
}
Annotation *shopAnnotation = [shopAnnotations objectAtIndex:index];
annotationView = [_mapView dequeueReusableAnnotationViewWithIdentifier:shopAnnotation.identifier];
if (!annotationView)
annotationView = [[[MKAnnotationView alloc] initWithAnnotation:shopAnnotation reuseIdentifier:shopAnnotation.identifier] autorelease];
for (UIView*view in annotationView.subviews)
{
[view removeFromSuperview];
}
annotationView.image = shopAnnotation.Image;
annotationView.alpha = 1.0f;
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
annotationView.userInteractionEnabled = YES;
if (shopAnnotation.bClicked==TRUE)
{
UIView *detailView = [[UIView alloc ] initWithFrame:CGRectMake(0, -50, 290, 56)];
detailView.userInteractionEnabled = YES;
detailView.superview = annotationView;
[detailView release];
UIImageView *bg = [[UIImageView alloc ] initWithImage:[UIImage imageNamed:#"bulle_carte.png"]];
[bg setFrame:CGRectMake(0, 0, 290, 56)];
bg.superview = detailView;
[bg release];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(250, 3, 35, 35)];
[button setImage:[UIImage imageNamed:#"fleche_bleue_d.png"] forState:UIControlStateNormal];
button.tag = [shopAnnotation.identifier intValue];
[button addTarget:self action:#selector(btnDetailPressed:) forControlEvents:UIControlEventTouchUpInside];
button.superview = detailView;
button.userInteractionEnabled = YES;
[annotationView setRightCalloutAccessoryView:detailView];
}
return annotationView;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSLog(#"calloutAccessoryControlTapped");
}
-(void)btnDetailPressed:(id)sender
{
NSLog(#"btnDetailPressed");
}
when I click on the button or inside the DetailView, btnDetailPressed or calloutAccessoryControlTapped are not called/triggered.
Any suggestions?
Use the MKMapViewDelegate's method mapView:didSelectAnnotationView::
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[YOUR_CUSTOM_CLASS class]]) {
//customize it
}
}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
if ([view isKindOfClass:[YOUR_CUSTOM_CLASS class]]) {
//do something
}
}
Apple's doc

MKAnnotation random order in MKMapView

I have a table view with an ordered list of objects, ordered by distance between me and the object. I need to show annotations in a map to show to the user the position of the objects but i need to show in the same order than table´s order because then i need to get with one has been pressed to show info of each object.
The problem is that when I put the annotations in the map each time I put them the tag number of the annotation is different. Is like the map added the annotations in a random order.
I have an annotations array and then I add that array to the map:
MKPointAnnotation* tallerAnnotation = [[MKPointAnnotation alloc] init];
[tallerAnnotation setCoordinate:CLLocationCoordinate2DMake([taller getLatitudTaller], [taller getLongitudTaller])];
[tallerAnnotation setTitle:[taller getNombre]];
[tallerAnnotation setSubtitle:[taller getDomicilio]];
[annotations addObject:tallerAnnotation];
And then add the array to the map:
[mapa addAnnotations:annotations];
Here is the code where I custom the annotation:
- (MKAnnotationView *) mapView: (MKMapView *) mapa viewForAnnotation: (id <MKAnnotation>) annotation_ {
MKPinAnnotationView *pin = (MKPinAnnotationView *) [self.mapa dequeueReusableAnnotationViewWithIdentifier: #"YourPinId"];
if (pin == nil) {
pin = [[MKPinAnnotationView alloc] initWithAnnotation:annotation_ reuseIdentifier: #"YourPinId"];
}
else {
pin.annotation = annotation_;
}
if ([[annotation_ title]isEqualToString:#"Tu posición"])
pin.pinColor = MKPinAnnotationColorRed;
else
{
[pin setCanShowCallout:YES];
pin.pinColor = MKPinAnnotationColorGreen;
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(getInfoTalleres:) forControlEvents:UIControlEventTouchUpInside];
[rightButton setTag:posicionActualTaller];
pin.rightCalloutAccessoryView = rightButton;
UILabel *l1=[[UILabel alloc] init];
l1.frame=CGRectMake(0, 5, 50, 15);
l1.backgroundColor = [UIColor clearColor];
l1.textColor = [UIColor whiteColor];
l1.font=[UIFont fontWithName:#"Arial Rounded MT Bold" size:(10.0)];
l1.text=[[[mainDelegate getTalleres]objectAtIndex: posicionActualTaller]getDistancia];
posicionActualTaller +=1;
UIView *leftCAV = [[UIView alloc] initWithFrame:CGRectMake(0,0,50,15)];
[leftCAV addSubview : l1];
pin.leftCalloutAccessoryView = leftCAV;
}
pin.animatesDrop = YES;
return pin;
}
I would like to do something like this:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSLog(#"Tag del taller = %i",[control tag]);
[mainDelegate setTallerActual:[[mainDelegate getTalleres]objectAtIndex:[control tag]]];
[self detalleTaller];
}
[control tag] has differents values each time I enter into map view so that way it´s impossible do something like [objects objectAtIndex:[control tag]];
Please I need help.
Thanks in advance.
Ok finally I have found a solution.
When I create the
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self action:#selector(getInfoTalleres:) forControlEvents:UIControlEventTouchUpInside];
for the annotation I assign the annotation title to the button this way:
[rightButton setTitle:[annotation_ subtitle] forState:UIControlStateNormal];
Then:
-(void)getInfoTalleres:(UIButton* )sender
{
for (int i = 0; i < [[mainDelegate getTalleres]count]; i++)
{
if ([[sender currentTitle] isEqualToString:[[[mainDelegate getTalleres]objectAtIndex:i]getDomicilio]])
{
[mainDelegate setTallerActual:[[mainDelegate getTalleres]objectAtIndex:i]];
[self detalleTaller];
break;
}
}
}
Hope somebody can use this solution.
Thanks a lot Cocoa.
Regards.
Check the Answer here it access title property Determine which MKPinAnnotationView was selected? and the tutorial http://www.scribd.com/doc/91629556/192/The-MKAnnotationView-class
let me know if you still not find answer

MKAnnotations not showing up until I scroll the map

Well, I have a view with a map where I load some annotations. Everything works fine, but when I want to erase those annotations and include other annotations they do not show up until I move (scroll) the map.
Any suggestion?
EDITED:
Seems like instead of using this:
[self updateMap];
I have to use:
[self performSelectorOnMainThread:#selector(updateMap) withObject:nil waitUntilDone:true];
Being update map the method where I add my new annotations.
Try smth like this:
[mapView removeAnnotations:[mapView annotations]];
NSArray *targetArray = /*YOUR ARRAY NAME with object, containing `latitude`, `longitude` and `title` values*/
for (id *item in targetArray) {
if (item.latitude && item.longitude) {
MKPin *pin = [[MKPin alloc] init]; // MKPin is your class which specifies the deledate `MKAnnotation`
pin.coordinate = CLLocationCoordinate2DMake(item.latitude, item.longitude);
pin.title = item.title;
[mapView addAnnotation:pin];
}
}
In the viewdidload use :
- (void)viewDidLoad
{
NSMutableArray* annotations=[[NSMutableArray alloc] init];
MyAnnotation* myAnnotation = [[MyAnnotation alloc] init];
myAnnotation.coordinate = theCoordinate;
[annotations addObject:myAnnotation];
MKMapRect flyTo = MKMapRectNull;
for (id <MKAnnotation> annotation in annotations)
{
NSLog(#"fly to on");
MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation.coordinate);
MKMapRect pointRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0);
if (MKMapRectIsNull(flyTo))
{
flyTo = pointRect;
}
else
{
flyTo = MKMapRectUnion(flyTo, pointRect);
//NSLog(#"else-%#",annotationPoint.x);
}
}
// Position the map so that all overlays and annotations are visible on screen.
mapView.visibleMapRect = flyTo;
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
NSLog(#"welcome into the map view annotation");
// if it's the user location, just return nil.
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
// try to dequeue an existing pin view first
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView* pinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
pinView.animatesDrop=YES;
pinView.canShowCallout=YES;
pinView.draggable = NO;
pinView.pinColor=MKPinAnnotationColorGreen;
//button on the right for popup for pins
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = rightButton;
//zoom button on the left of popup for pins
UIButton* leftButton = [UIButton buttonWithType:UIButtonTypeContactAdd];
[leftButton setTitle:annotation.title forState:UIControlStateNormal];
[leftButton addTarget:self
action:#selector(zoomToLocation:) forControlEvents:UIControlEventTouchUpInside];
pinView.leftCalloutAccessoryView = leftButton;
UIImageView *profileIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"profile.png"]];
pinView.leftCalloutAccessoryView = profileIconView;
[profileIconView release];
return pinView;
}
Hopefully this helps !!!!!!!!!

Optimizing Code for MKMapView - Large Number of Annotations

I have a modal view in my app which displays a UIMapView. I then add a large number of annotations (over 800) to this map view (code below).
The problem is that the user is forced to wait a minute or so while all the pins load. Also the app becomes sluggish once all 800 pins are on the map.
Can anyone suggest how I can improve my code below ?
Thank you.
#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;
}
The two biggest speed improvements you can make here are:
Implement annotation view re-use (right now it creates a new view every time it needs to show an annotation even if the same one comes into view again.
Change how the UniqueID is set. To set it, the code is currently looping through all the annotations every time it creates an annotation view (which could happen any time the map view is zoomed or scrolled--not just the initial time).
First, instead of searching for the UniqueID in the viewForAnnotation method and using a button tag to pass the annotation identifier, add UniqueID as a property to your custom annotation class MyLocation and set the property when you add the annotation itself in addPins:
annotation.uniqueID = info.UniqueID; // <-- give id to annotation itself
[mapViewLink addAnnotation:annotation];
You could also add uniqueID as a parameter to the initWithName method instead of assigning the property separately.
Next, to implement annotation view re-use, the viewForAnnotation method should look like this:
- (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;
}
Finally, to respond to the button press and figure out which UniqueID to show the detail for, implement the calloutAccessoryControlTapped delegate method:
- (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...
}
After all these changes, only the initial loading of the annotations will take up most of the time. If that is still a problem, one solution is to only add annotations that would be visible in the currently displayed region and add/remove annotations as the user changes the visible region.
I completely agree with Anna. But consider that 800 AnnotationViews at the same time will result in a extreme laggy interface. So if your map should provide user interaction like scrolling or zooming you better implement some kind clustering of your annotation views.