Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

MKAnnotation problem

PanterloPanterlo Posts: 1New Users
edited February 2010 in iOS SDK Development
Due to restrictions in the agreement I am not really sure how much "you can talk" about but the map function has been out in the public so my question is simple, has anyone tried annotations and got it working successfully ?
Post edited by Panterlo on

Replies

  • craiglittlecraiglittle Posts: 105Registered Users
    edited March 2009
    Yes, including the callout views and responding to callout tap events. I would recommend following the Docco rather than relying on sample code, as most of the sample code I have seen has been inaccurate.

    One thing I will point out that is unclear in the documentation is creating the view for the callout. The viewForCalloutAccessoryPosition: method can return any type of UIView descendant, but if you want to respond to user taps (via the mapView:annotationView:accessoryButtonTappedAtPosition: method) then you have to create it as a UIButton. The docco doesn't explicitly state this, but on my 12th reading I noticed that the docco hints at this.
    The important thing is not so much that every child should be taught, as that every child should be given the wish to learn. <br />
    <i> - Sir John Lubbock.</i>
  • lapselapse Posts: 211Registered Users
    edited March 2009
    Annotations were a cinch to set up. I had to add the annotations to the map on viewDidAppear to get the pin drop animations working:
    - (void) viewDidAppear: (BOOL) animated
    {
            [self.mapView addAnnotations: _points];
    }
    
  • PhilSimpsonPhilSimpson Posts: 6New Users
    edited March 2009
    lapse wrote: »
    Annotations were a cinch to set up. I had to add the annotations to the map on viewDidAppear to get the pin drop animations working:
    - (void) viewDidAppear: (BOOL) animated
    {
            [self.mapView addAnnotations: _points];
    }
    

    I am able to create an annotation object but I can't make it display on the mapView. The docs say that a new annotationView will be created automatically but how do I link this to my annotation? ANy help much appreciated!
  • lapselapse Posts: 211Registered Users
    edited March 2009
    It's not created automatically. You need to implement this delegate method which will itself be called automatically by the MKMapView:
    - (MKAnnotationView *) mapView: (MKMapView *) mapView viewForAnnotation: (id&lt;MKAnnotation&gt;) annotation
    {
            MKPinAnnotationView *pin = (MKPinAnnotationView *) [self.mapView dequeueReusableAnnotationViewWithIdentifier: @&quot;asdf&quot;];
            if (pin == nil)
            {
                    pin = [[[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: @&quot;asdf&quot;] autorelease];
            }
            else
            {
                    pin.annotation = annotation;
            }
            pin.pinColor = MKPinAnnotationColorRed;
            pin.animatesDrop = YES;
            return pin;
    }
    
    
  • PhilSimpsonPhilSimpson Posts: 6New Users
    edited March 2009
    Aha! So like cell views in tables then! That's solved it, thanks very much!

    I have noticed one other weirdness though. Using mapView setRegion:animated: seems to cause my map to zoom out to exactly half it's previous zoom level. I'm storing the span value in mapView regionDidChange:animated: and handing it back to mapView setRegion:animated but it seems to ignore me! The idea is that the user can scroll & zoom and when the app moves the map, it retains the user's zoom level.

    Anyone else come across this? Any insight on where I'm going wrong?
  • PhilSimpsonPhilSimpson Posts: 6New Users
    edited April 2009
    Beta 2 seems to have broken pinColors. Mine all appear red now. I noticed that the span issue I was having was listed as being fixed in beta 2, but I'm still getting zooming out when using setRegion.

    Anyone?
  • craiglittlecraiglittle Posts: 105Registered Users
    edited April 2009
    I also had problems getting the location indicator to show properly. It worked in the simulator (showed a blue dot at Cupertino), but no blue dot for my location when I tested on my upgraded iPhone...

    It appears that the mapView:viewForAnnotation: delegate method is now called for the location annotation as well as your manually added annotations, a behaviour slightly different from Beta 1. Because I processed it as one of my annotations, it had a red pin on the map instead of a blue dot, and because I have 69 annotations it got lost in the clutter.

    I now use the following code (sort of) to determine whether I want to display a pin annotation (for my annotations) or the blue location dot:
    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id &lt;MKAnnotation&gt;)annotation {
    	static NSString *defaultPinID = @&quot;CameraAnnotation&quot;;
    	MKPinAnnotationView *retval = nil;
    	
    	if ([annotation isMemberOfClass:[CameraAnnotation class]]) {
    		retval = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
    		if (retval == nil) {
    			retval = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
    		}
    		
    		if (retval) {
    			[retval setPinColor:MKPinAnnotationColorGreen];
    			retval.animatesDrop = YES;
    			retval.canShowCallout = NO;
    		}
    	}
    	
        return retval;
    }
    
    The important thing is not so much that every child should be taught, as that every child should be given the wish to learn. <br />
    <i> - Sir John Lubbock.</i>
  • David CasseresDavid Casseres Posts: 10Registered Users
    edited April 2009
    Yes, including the callout views and responding to callout tap events. I would recommend following the Docco rather than relying on sample code, as most of the sample code I have seen has been inaccurate.

    One thing I will point out that is unclear in the documentation is creating the view for the callout. The viewForCalloutAccessoryPosition: method can return any type of UIView descendant, but if you want to respond to user taps (via the mapView:annotationView:accessoryButtonTappedAtPosition: method) then you have to create it as a UIButton. The docco doesn't explicitly state this, but on my 12th reading I noticed that the docco hints at this.

    The viewForCalloutAccessoryPosition: method doesn't exist in the 3.0 Beta 3 SDK. So my question is, has anyone succeeded in annotating a map in Beta 3? When I call addAnnotation: on the map view, an exception is thrown from fairly deep down in Apple's code. I've filed a bug report.
  • PhilSimpsonPhilSimpson Posts: 6New Users
    edited April 2009
    For what it's worth, my app works under beta 3, but it's not adding accessory stuff to the callouts, it's just showing the pins (purple and green are back) and giving title and subtitle when tapped. Does your app still throw an exception with accessory bits commented out?
  • David CasseresDavid Casseres Posts: 10Registered Users
    edited April 2009
    For what it's worth, my app works under beta 3, but it's not adding accessory stuff to the callouts, it's just showing the pins (purple and green are back) and giving title and subtitle when tapped. Does your app still throw an exception with accessory bits commented out?

    I haven't even reached the point of trying to do anything with callouts – all I do is create an instance of a very simple class that implements MKAnnotation, and add it to the map view using addAnnotation:. An exception is immediately thrown from from several frames down in the MapKit code, and it looks like an out-of-bounds index for an NSArray is causing it.

    I've also tried using an MKPlacemark object (created by a reverse geocoder) instead of my own custom class, and exactly the same thing happens.
  • PhilSimpsonPhilSimpson Posts: 6New Users
    edited April 2009
    I haven't even reached the point of trying to do anything with callouts – all I do is create an instance of a very simple class that implements MKAnnotation, and add it to the map view using addAnnotation:. An exception is immediately thrown from from several frames down in the MapKit code, and it looks like an out-of-bounds index for an NSArray is causing it.

    I've also tried using an MKPlacemark object (created by a reverse geocoder) instead of my own custom class, and exactly the same thing happens.

    OK, here's my AnnotationListObject.h file:

    #import <Foundation/Foundation.h>
    #import <MapKit/MapKit.h>

    @interface AnnotationListObject : NSObject <MKAnnotation> {
    CLLocationCoordinate2D coordinate;
    NSString *title;
    NSString *subtitle;
    }
    @property (nonatomic) CLLocationCoordinate2D coordinate;
    @property (nonatomic, retain) NSString *title;
    @property (nonatomic, retain) NSString *subtitle;
    - (void) moveAnnotation: (CLLocationCoordinate2D) newCoordinate;
    @end


    And the AnnotationListObject.m file:

    #import "AnnotationListObject.h"

    @implementation AnnotationListObject

    @synthesize coordinate, title, subtitle;

    - (void) moveAnnotation: (CLLocationCoordinate2D) newCoordinate {
    coordinate = newCoordinate;
    }

    @end


    and the relevant calls from RootViewController:

    - (MKAnnotationView *) mapView: (MKMapView *) mapView viewForAnnotation: (id<MKAnnotation>) annotation {
    MKPinAnnotationView *pin = (MKPinAnnotationView *) [map dequeueReusableAnnotationViewWithIdentifier: [annotation title]];
    if (pin == nil)
    {
    pin = [MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: [annotation title autorelease];
    }
    else
    {
    pin.annotation = annotation;
    }
    pin.pinColor = MKPinAnnotationColorGreen;
    pin.animatesDrop = YES;
    pin.canShowCallout = TRUE;
    return pin;
    }

    - (void) doAnnotations { // call this from viewDidAppear or somesuch
    NSMutableArray annotationList = [NSMutableArray new];
    // create loop here if necessary
    AnnotationListObject *newAnnotation = [AnnotationListObject new];
    CLLocationCoordinate2D tempCoordinate;
    tempCoordinate.latitude = 0.0; // set latitude to required value
    tempCoordinate.longitude = 0.0; // set longitude to required value
    [newAnnotation setCoordinate: tempCoordinate];
    [newAnnotation setTitle: @Title]; // or whatever
    [newAnnotation setSubtitle: @Subtitle]; // or whatever
    [annotationList addObject: newAnnotation];
    newAnnotation release];
    // end loop here if looped
    [map addAnnotations: annotationList];
    }

    this is all assuming you have an MKMapView called 'map' correctly connected in Interface Builder. Import the 'AnnotationViewList.h' in the RootViewController file and it should behave. It does for me. Now, if only I could get setRegion:animated: to behave...
  • David CasseresDavid Casseres Posts: 10Registered Users
    edited April 2009
    OK, here's my AnnotationListObject.h file:

    #import <Foundation/Foundation.h>
    #import <MapKit/MapKit.h>

    @interface AnnotationListObject : NSObject <MKAnnotation> {
    CLLocationCoordinate2D coordinate;
    NSString *title;
    NSString *subtitle;
    }
    @property (nonatomic) CLLocationCoordinate2D coordinate;
    @property (nonatomic, retain) NSString *title;
    @property (nonatomic, retain) NSString *subtitle;
    - (void) moveAnnotation: (CLLocationCoordinate2D) newCoordinate;
    @end


    And the AnnotationListObject.m file:

    #import "AnnotationListObject.h"

    @implementation AnnotationListObject

    @synthesize coordinate, title, subtitle;

    - (void) moveAnnotation: (CLLocationCoordinate2D) newCoordinate {
    coordinate = newCoordinate;
    }

    @end


    and the relevant calls from RootViewController:

    - (MKAnnotationView *) mapView: (MKMapView *) mapView viewForAnnotation: (id<MKAnnotation>) annotation {
    MKPinAnnotationView *pin = (MKPinAnnotationView *) [map dequeueReusableAnnotationViewWithIdentifier: [annotation title]];
    if (pin == nil)
    {
    pin = [MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: [annotation title autorelease];
    }
    else
    {
    pin.annotation = annotation;
    }
    pin.pinColor = MKPinAnnotationColorGreen;
    pin.animatesDrop = YES;
    pin.canShowCallout = TRUE;
    return pin;
    }

    - (void) doAnnotations { // call this from viewDidAppear or somesuch
    NSMutableArray annotationList = [NSMutableArray new];
    // create loop here if necessary
    AnnotationListObject *newAnnotation = [AnnotationListObject new];
    CLLocationCoordinate2D tempCoordinate;
    tempCoordinate.latitude = 0.0; // set latitude to required value
    tempCoordinate.longitude = 0.0; // set longitude to required value
    [newAnnotation setCoordinate: tempCoordinate];
    [newAnnotation setTitle: @Title]; // or whatever
    [newAnnotation setSubtitle: @Subtitle]; // or whatever
    [annotationList addObject: newAnnotation];
    newAnnotation release];
    // end loop here if looped
    [map addAnnotations: annotationList];
    }

    this is all assuming you have an MKMapView called 'map' correctly connected in Interface Builder. Import the 'AnnotationViewList.h' in the RootViewController file and it should behave. It does for me. Now, if only I could get setRegion:animated: to behave...


    It turns out my problem was very simple: I was not setting a delegate for the MKMapView. It seems a bit rude for the MapKit to throw an exception for that, but the whole thing was my mistake.

    Thanks for your sample code, which may help me even though my problem was something else.
  • PhilSimpsonPhilSimpson Posts: 6New Users
    edited May 2009
    It turns out my problem was very simple: I was not setting a delegate for the MKMapView. It seems a bit rude for the MapKit to throw an exception for that, but the whole thing was my mistake.

    Thanks for your sample code, which may help me even though my problem was something else.

    You're welcome. For anyone that hasn't tried it yet, beta 4's new MKMapView SetCenterCoordinate:Animated: works a treat - no more unwanted zooming.
  • pwbpwb Posts: 2New Users
    edited September 2009
    lapse wrote: »
    It's not created automatically. You need to implement this delegate method which will itself be called automatically by the MKMapView:
    - (MKAnnotationView *) mapView: (MKMapView *) mapView viewForAnnotation: (id&lt;MKAnnotation&gt;) annotation
    {
            MKPinAnnotationView *pin = (MKPinAnnotationView *) [self.mapView dequeueReusableAnnotationViewWithIdentifier: @&quot;asdf&quot;];
            if (pin == nil)
            {
                    pin = [[[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: @&quot;asdf&quot;] autorelease];
            }
            else
            {
                    pin.annotation = annotation;
            }
            pin.pinColor = MKPinAnnotationColorRed;
            pin.animatesDrop = YES;
            return pin;
    }
    
    

    Have you seen evidence that AnnotationViews are actually getting placed on the reuse queue? I have code very similar to the above, but placed in NSLog statements to see when I was reusing and creating new annotations. And it never reuses an annotation. :confused:
  • pwbpwb Posts: 2New Users
    edited September 2009
    Beta 2 seems to have broken pinColors. Mine all appear red now. I noticed that the span issue I was having was listed as being fixed in beta 2, but I'm still getting zooming out when using setRegion.

    Anyone?

    I'm replying to Phils comment because I think this code is potentially an answer to why all pins might appear red. I have the following code in my app, and it works. But can anyone tell me why it doesn't result in an infinite loop?
    - (MKAnnotationView *)mapView:(MKMapView *)passedMapView viewForAnnotation:(id &lt;MKAnnotation&gt;)annotation { 
    	MKAnnotationView *annotationView; 
    
    	
    	if ([annotation class] == [MKUserLocation class] ) { 
    		NSLog(@&quot;Detected UserLocationAnnotation&quot;); 
            	annotationView = [passedMapView viewForAnnotation:annotation]; 
    		[self doSomeStuffHere];
    	} else { 
              // Do other stuff for custom Annotation 
            }
    	return annotationView; 
    }
    
  • sijo006sijo006 Posts: 23Registered Users
    edited February 2010
    Can u help me in my problem.. I have to show 4 lines of data in that bubble..Like One title..then description, date, location name.. All the example showing only 2 lines of details. i tried like appending wanted data in subtitle and seperated by a \n character.. But it didnt worked.. Plz help me
  • David CasseresDavid Casseres Posts: 10Registered Users
    edited February 2010
    sijo006 wrote: »
    Can u help me in my problem.. I have to show 4 lines of data in that bubble..Like One title..then description, date, location name.. All the example showing only 2 lines of details. i tried like appending wanted data in subtitle and seperated by a \n character.. But it didnt worked.. Plz help me

    I wish I had an answer for you. But the MKAnnotation API only allows one string in the title and one in the subtitle.

    Anyone else?
Sign In or Register to comment.