1

I know this question has been asked by others before and i have read them in this forum previously, but I have tried all the proposed approach without luck so far so I decided to post this question.

I have this piece of code below which is meant to change the pin icon on MKMapView. However the viewForAnnotation function doesn't even seem to get called by the MKMapView. People said that they got some problems with delegating the function to the file's owner which can be done by dragging the map view in .xib file to the file owner or defining myMap.delegate = self. I have done both ways but still get nothing.

Really appreciate for any help for my problem, thanks.

CODE:

- (MKPinAnnotationView*)myMap:(MKMapView*)myMap viewForAnnotation:(id<MKAnnotation>)annotation{

    MKPinAnnotationView *pin = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:@"CustomPin"];

    UIImage *icon = [UIImage imageNamed:@"bustour.png"];
    UIImageView *iconView = [[UIImageView alloc] initWithFrame:CGRectMake(8,0,32,37)];

    if(icon == nil)
        NSLog(@"image: ");
    else
        NSLog(@"image: %@", (NSString*)icon.description);

    [iconView setImage:icon];
    [pin addSubview:iconView];
    pin.canShowCallout = YES;
    pin.pinColor = MKPinAnnotationColorPurple;

    return pin;
}

DELEGATION enter image description here

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Chris Wijaya
  • 1,276
  • 3
  • 16
  • 34

3 Answers3

4

Your delegate method is named incorrectly as myMap:viewForAnnotation:.

The viewForAnnotation delegate method must be named mapView:viewForAnnotation: like this:

- (MKAnnotationView *)mapView:(MKMapView *)mapView 
            viewForAnnotation:(id < MKAnnotation >)annotation
{
    //code goes here...
}

The map view will look for that exact method name.
If not found, it won't call it and will create a default red pin instead.


You can change the name of the internal parameters but not the method name.

For example, this would also be ok:

- (MKAnnotationView *)mapView:(MKMapView *)myMap 
            viewForAnnotation:(id < MKAnnotation >)annotation
{
    //code goes here...
}
  • Thanks @Anna, right on the spot! I still have a question here, if you don't mind, in my code I basically named my mapView as myMap as seen in the code. Why does the delegation method came from the mapView which I didn't define/create? Where did it come from? – Chris Wijaya Jul 01 '13 at 23:58
  • 1
    The delegate method name is required by the MKMapViewDelegate protocol. As per Objective-C rules, since you want to conform to that protocol, you must name your method accordingly. Any map view object, regardless of what you name it, will look for that delegate method name (that's the delegate/protocol contract -- that's how it works or how the language is designed). As I said, you can still change the name of the internal parameters to anything you want. They don't even have to match what you named the objects outside the method. –  Jul 02 '13 at 00:42
  • 1
    When the map view object calls that delegate method, it passes a reference to itself as the first parameter. In that method, the parameter name could be anything but it still refers to the same map view object that called it. If still not clear, you may want read an Objective-C or protocol intro (developer.apple.com has good documentation on it). –  Jul 02 '13 at 00:44
  • Sorry I needed sometime to digest the lesson and researches. I have come to an understanding that the mapView object itself got created once the Map View object dragged in on top of the View object in xib file. And to use it's method we have to delegate the mapView to the UIViewController class which acts as the file's owner. Thus in my case here, the IBOutlet *myMap definition acts as the reference object to manipulate mapView object's properties. – Chris Wijaya Jul 02 '13 at 04:24
  • So in simple words, delegate acts as the base object's methods modifier and IBOutlet/IBAction acts as the base object's properties modifier. Can I say that? – Chris Wijaya Jul 02 '13 at 04:27
  • 1
    The delegate is not a method "modifier" but more accurately a method "implementer". The IBOutlet and IBAction are not directly related to the delegate/protocol concept -- they are simply tags in the code that Interface Builder looks for to know what connections are available for it to present to you in its UI. The map view (or any object) and its delegate can all be implemented in code without the use of IB (which is mostly a design convenience). –  Jul 02 '13 at 12:15
  • Thanks heaps. Really appreciate the answers there for explaining the delegate and outlet/action concept. You're just like iOS wiki :) – Chris Wijaya Jul 02 '13 at 13:34
0

import bellow class in your .h class..

#import <MapKit/MapKit.h>

and also add MKMapViewDelegate in your this class like bellow...

@interface PTAViewController : UIViewController<MKMapViewDelegate>{

  ///...... your code..

}

@end
Paras Joshi
  • 20,427
  • 11
  • 57
  • 70
  • i have imported the mapkit header in the .pch (the lazy way) so that i don't have to include it in every header file. do they have different impact? – Chris Wijaya Jul 01 '13 at 11:09
  • no no but you define delegate like above code `UIViewController `?? try it out and also in `viewDidLoad:` method give Delegate to SELF to MapView... – Paras Joshi Jul 01 '13 at 11:10
  • Hi, tried it out and i had this error: [UIViewController _loadViewFromNibNamed:bundle:] loaded the "PTAViewController" nib but the view outlet was not set.' – Chris Wijaya Jul 01 '13 at 11:25
  • check thew whole outlet from your nib with main view.. i think not give outlet perfactly... – Paras Joshi Jul 01 '13 at 11:26
  • hi, finally figured out the error. messed up the view outlet as u said but still didn't call out the viewForAnnotation function – Chris Wijaya Jul 01 '13 at 11:59
  • you give the outlet and delegate to self to MapView and view also??? and write this line in viewDidLoad... `mapView.delegate = self;` .. – Paras Joshi Jul 01 '13 at 12:01
  • 1
    Hi, really appreciate your help. Somehow I cut off my view outlet and assigned delegate to it. that what messed it up and i fixed it by assigning the delegate to the file's owner and the outlet to myMap which MKMapView for the mapView and assigning back the view's outlet to file's owner. – Chris Wijaya Jul 01 '13 at 12:32
0

As I understand, you setting outlet, not delegate. To set delegate do like that:enter image description here

Renderhp
  • 386
  • 2
  • 6
  • Hi, i tried it out but i had an error: [UIViewController _loadViewFromNibNamed:bundle:] loaded the "PTAViewController" nib but the view outlet was not set. I got lost now i suppose – Chris Wijaya Jul 01 '13 at 11:26