MKMapView: Issue with changing pin image - ios

I am trying to change the standard pin to my own image but I keep failing after several attempts.
I have tried different codes and guides that I have found here in this forum but none of them seems to work. I belive I am pasting the code in to my project wrongly. Any ideas how to replace the regular pin with my own image?
//.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MapPin : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
- (id)initWithLocation:(CLLocationCoordinate2D)coord;
#end
//.m
#import <Foundation/Foundation.h>
#import "MapPin.h"
#implementation MapPin
#synthesize coordinate,title,subtitle;
- (id)initWithLocation:(CLLocationCoordinate2D)coord{
self = [super init];
if (self) {
coordinate = coord;
}
return self;
}
#end
//Viewcontroller.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface FirstViewController : UIViewController <UIAlertViewDelegate, UIWebViewDelegate> {
MKMapView *mapview;
}
- (IBAction)information;
#property (strong, nonatomic) IBOutlet UIScrollView *ScrollView;
#property (strong, nonatomic) IBOutlet UIImageView *image;
#property (retain, nonatomic) IBOutlet MKMapView *mapview;
- (IBAction)showMenu;
- (IBAction)setMap:(id)sender;
- (IBAction)GetLocation:(id)sender;
#end
//Viewcontroller.m
#import "FirstViewController.h"
#import "MapPin.h"
#implementation FirstViewController
#synthesize ScrollView, image;
#synthesize mapview;
- (void)viewDidLoad{
MKCoordinateRegion region = { {0.0, 0.0}, {0.0,0.0}};
region.center.latitude = 55.709900;
region.center.longitude = 13.201207;
region.span.longitudeDelta = 0.032f;
region.span.latitudeDelta = 0.032f;
[mapview setRegion:region animated:YES];
MapPin *ann = [[MapPin alloc] init];
ann.title = #"test Town";
ann.subtitle = #"test Nation";
ann.coordinate = region.center;
ann.coordinate = region.center;
[mapview addAnnotation:ann];
MKCoordinateRegion region2 = { {0.0, 0.0}, {0.0,0.0}};
region2.center.latitude = 55.703904;
region2.center.longitude = 13.201207;
region2.span.longitudeDelta = 0.032f;
region2.span.latitudeDelta = 0.032f;
[mapview setRegion:region2 animated:YES];
MapPin *ann2 = [[MapPin alloc] init];
ann2.title = #"test Town";
ann2.subtitle = #"test Nation";
ann2.coordinate = region2.center;
ann2.coordinate = region2.center;
[mapview addAnnotation:ann2];
ScrollView.scrollEnabled = YES;
[ScrollView setContentSize:CGSizeMake(320, 515)];
}
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKPinAnnotationView* pinView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier];
pinView.animatesDrop=YES;
pinView.canShowCallout=YES;
pinView.pinColor= MKPinAnnotationColorGreen;
pinView.enabled = YES;
pinView.canShowCallout = YES;
pinView.image=[UIImage imageNamed:#"test.png"]; //here I am giving the image
return pinView;
}

See my other answer for working implementation.
Setting an IBOutlet delegate:
Since you're using an IBOutlet for your MKMapView you should control-drag from your MKMapView in your storyboard/xib file to the ViewController/"File's Owner" and select "delegate" from the popup.
Here a SO answer that covers creating custom pins: Custom pins
Also,
pinView.image=[UIImage imageNamed:#"test.png"];
should be
pinView.image=[UIImage imageNamed:#"test"];
Reference: Image from imageNamed:

The following worked for me:
Make sure MapKit.framework has been added to your project.
Make sure test.png is in your project (preferably in Images.xcassets)
Control-drag from your mapView in your storyboard to the ViewController and connect "delegate".
Then...
#import "MapPin.h"
#import <MapKit/MapKit.h>
#interface ViewController () <MKMapViewDelegate>
#property (weak, nonatomic) IBOutlet MKMapView *mapview;
#end
#implementation ViewController
- (void)viewDidLoad
{
MKCoordinateRegion region = { {0.0, 0.0}, {0.0,0.0}};
region.center.latitude = 55.709900;
region.center.longitude = 13.201207;
region.span.longitudeDelta = 0.032f;
region.span.latitudeDelta = 0.032f;
[self.mapview setRegion:region animated:YES];
MapPin *ann = [[MapPin alloc] init];
ann.title = #"test Town";
ann.subtitle = #"test Nation";
ann.coordinate = region.center;
ann.coordinate = region.center;
[self.mapview addAnnotation:ann];
MKCoordinateRegion region2 = { {0.0, 0.0}, {0.0,0.0}};
region2.center.latitude = 55.703904;
region2.center.longitude = 13.201207;
region2.span.longitudeDelta = 0.032f;
region2.span.latitudeDelta = 0.032f;
[self.mapview setRegion:region2 animated:YES];
MapPin *ann2 = [[MapPin alloc] init];
ann2.title = #"test Town";
ann2.subtitle = #"test Nation";
ann2.coordinate = region2.center;
ann2.coordinate = region2.center;
[self.mapview addAnnotation:ann2];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if(annotationView) {
return annotationView;
} else {
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:AnnotationIdentifier];
annotationView.image = [UIImage imageNamed:#"test"];
return annotationView;
}
}
#end

So I have followed the guidelines above, added the line of code and step3. Control-drag from your mapView in your storyboard to the ViewController and connect "delegate". which I named "pin".
But my image wont appear...I'll paste the new code again..there must be something wrong in it.
//Viewcontroller.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface FirstViewController : UIViewController <UIAlertViewDelegate, UIWebViewDelegate, MKMapViewDelegate> {
MKMapView *mapview;
}
- (IBAction)information;
#property (strong, nonatomic) IBOutlet UIScrollView *ScrollView;
#property (strong, nonatomic) IBOutlet UIImageView *image;
#property (retain, nonatomic) IBOutlet MKMapView *mapview;
#property (strong, nonatomic) IBOutlet MKMapView *pin;
- (IBAction)showMenu;
- (IBAction)setMap:(id)sender;
- (IBAction)GetLocation:(id)sender;
#end
//Viewcontroller.m
#import "FirstViewController.h"
#import "MapPin.h"
#implementation FirstViewController
#synthesize ScrollView, image;
#synthesize mapview;
#synthesize pin;
- (void)viewDidLoad{
MKCoordinateRegion region = { {0.0, 0.0}, {0.0,0.0}};
region.center.latitude = 55.709900;
region.center.longitude = 13.201207;
region.span.longitudeDelta = 0.032f;
region.span.latitudeDelta = 0.032f;
[self.mapview setRegion:region animated:YES];
MapPin *ann = [[MapPin alloc] init];
ann.title = #"test Town";
ann.subtitle = #"test Nation";
ann.coordinate = region.center;
ann.coordinate = region.center;
[self.mapview addAnnotation:ann];
MKCoordinateRegion region2 = { {0.0, 0.0}, {0.0,0.0}};
region2.center.latitude = 55.703904;
region2.center.longitude = 13.201207;
region2.span.longitudeDelta = 0.032f;
region2.span.latitudeDelta = 0.032f;
[self.mapview setRegion:region2 animated:YES];
MapPin *ann2 = [[MapPin alloc] init];
ann2.title = #"test Town";
ann2.subtitle = #"test Nation";
ann2.coordinate = region2.center;
ann2.coordinate = region2.center;
[self.mapview addAnnotation:ann2];
ScrollView.scrollEnabled = YES;
[ScrollView setContentSize:CGSizeMake(320, 515)];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if(annotationView) {
return annotationView;
} else {
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:AnnotationIdentifier];
annotationView.image = [UIImage imageNamed:#"test"];
return annotationView;
}
}
#end

Related

Set size of annotation icon in MKMapView - iOS

I am trying to display some icons on a MKMapView. I have achieved that by using this code:
MapPoint *placeObject = [[MapPoint alloc] initWithName:place.name
address:place.address
coordinate:place.location.coordinate
image:place.customMapPinImage
icon:place.icon
bookmark:place.bookmark
contents_ID:place.contents_ID
contents_lang_MAIN_ID:place.contents_lang_MAIN_ID
contents_lang_ID_ML:place.contents_lang_ID_ML];
[mapView addAnnotation:placeObject];
The problem is that, without changing anything in the code, the size of the icons changed and I don't know why. How can I adjust the size of the icons?
You need to write class annotations
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface Annotation : NSObject <MKAnnotation>
#property (nonatomic) CLLocationCoordinate2D coordinate;
#property (strong, nonatomic) NSString *myTitle;
+ (Annotation *)initAnnotation:(CLLocationCoordinate2D)coordinate title:(NSString *)title;
#end
Implementation
#import "Annotation.h"
#implementation Annotation
+ (Annotation *)initAnnotation:(CLLocationCoordinate2D)coordinate title:(NSString *)title
{
return [[Annotation alloc] initWithAnnotation:coordinate title:title];
}
- (instancetype)initWithAnnotation:(CLLocationCoordinate2D)coordinate title:(NSString *)title
{
self = [super init];
self.coordinate = coordinate;
self.myTitle = title;
return self;
}
#end
ViewController
#import "ViewController.h"
#import <MapKit/MapKit.h>
#import "Annotation.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//set coordinates
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(51.50851, -0.02172);
//add annotation
Annotation *annotation = [Annotation initAnnotation:coordinate title:#"Annotation"];
[self.mapView addAnnotation:annotation];
[self.mapView showAnnotations:#[annotation] animated:YES];
// add circle with radius
MKCircle *circle = [MKCircle circleWithCenterCoordinate:annotation.coordinate radius:10000];
[self.mapView addOverlay:circle];
//add region by coordinates
MKCoordinateRegion region;
region.center.latitude = 51.50851;
region.center.longitude = -0.02172;
// level zoom
region.span.latitudeDelta = 1;
region.span.longitudeDelta = 1;
region = [self.mapView regionThatFits:region];
[self.mapView setRegion:region animated:YES];
}
Do not forget to set the controller as a map delegate, and implement the circle mapping method
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>) overlay{
MKCircleRenderer *circleView = [[MKCircleRenderer alloc] initWithOverlay:overlay];
circleView.fillColor = [[UIColor greenColor] colorWithAlphaComponent:0.4];
return circleView;
}[![enter image description here][1]][1]
Pin appears, and you can adjust its size
https://prntscr.com/lvfjwi

Open a new view using mapPin button Xcode

I am developing an app in Xcode (objective-c). My app has a TableView with a list of restaurants and when you press one row, another view is opened with the restaurant information. The method I am using is that I am sending the title in the row to the new view and depending on the title I load the information of the restaurant.
I want to do exactly the same using a map pin button. I have a map with pins and I want to press the right detail button an open another view with the restaurant information depending on the mapPin title.
Can someone help me! I was looking for tutorial and other posts but it doesn't work in my case. Thank you very much!
This is my MapViewController.h:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController {
MKMapView *mapView;
}
#property (weak, nonatomic) IBOutlet UIBarButtonItem *barButton;
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
-(IBAction)setMap:(id)sender;
#end
This is my MapViewController.m:
#import "MapViewController.h"
#import "SWRevealViewController.h"
#import "RestMapPin.h"
#import "RestViewController.h"
#interface MapViewController ()
#end
#implementation MapViewController
#synthesize mapView;
- (void)viewDidLoad {
[super viewDidLoad];
_barButton.target = self.revealViewController;
_barButton.action = #selector(revealToggle:);
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
[self.navigationItem setTitle:NSLocalizedString (#"Map", nil)]; /*Cambia el titulo del navigation controller*/
[self.navigationController.navigationBar setTitleTextAttributes:#{NSForegroundColorAttributeName : [UIColor whiteColor]}]; /*Cambia el color de las letras del navigation controller bar del menu principal*/
[self.navigationController.navigationBar setBarTintColor:[UIColor colorWithRed:27/255.0f green:101/255.0f blue:163/255.0f alpha:1.0f]];
self.navigationController.navigationBar.tintColor = [UIColor whiteColor]; /*Cambia el color del boton de la izquierda*/
mapView.delegate = self;
//1
//80 Grados
MKCoordinateRegion region_80_grados = { {0.0, 0.0}, {0.0, 0.0}};
region_80_grados.center.latitude = 40.42871179999999;
region_80_grados.center.longitude = -3.703639100000032;
region_80_grados.span.longitudeDelta = 0.1f;
region_80_grados.span.latitudeDelta = 0.1f;
[mapView setRegion:region_80_grados animated:YES];
RestMapPin *ann_80_grados = [[RestMapPin alloc] init];
ann_80_grados.title = #"80 Grados";
ann_80_grados.subtitle = #"Malasaña";
ann_80_grados.coordinate = region_80_grados.center;
[mapView addAnnotation:ann_80_grados];
//90 Grados
MKCoordinateRegion region_90_grados = { {0.0, 0.0}, {0.0, 0.0}};
region_90_grados.center.latitude = 40.4164161;
region_90_grados.center.longitude = -3.6699459999999817;
region_90_grados.span.longitudeDelta = 0.1f;
region_90_grados.span.latitudeDelta = 0.1f;
[mapView setRegion:region_90_grados animated:YES];
RestMapPin *ann_90_grados = [[RestMapPin alloc] init];
ann_90_grados.title = #"90 Grados";
ann_90_grados.subtitle = #"Retiro";
ann_90_grados.coordinate = region_90_grados.center;
[mapView addAnnotation:ann_90_grados];
/*B&B Babel*/
MKCoordinateRegion region_babel = { {0.0, 0.0}, {0.0, 0.0}};
region_babel.center.latitude = 40.4214535;
region_babel.center.longitude = -3.6974301;
region_babel.span.longitudeDelta = 0.1f;
region_babel.span.latitudeDelta = 0.1f;
[mapView setRegion:region_babel animated:YES];
RestMapPin *ann_babel = [[RestMapPin alloc] init];
ann_babel.title = #"B&B Babel";
ann_babel.subtitle = #"Barrio de Chueca";
ann_babel.coordinate = region_babel.center;
[mapView addAnnotation:ann_babel];
/*Babelia*/
MKCoordinateRegion region_Babelia = { {0.0, 0.0}, {0.0, 0.0}};
region_Babelia.center.latitude = 40.4234778;
region_Babelia.center.longitude = -3.686283000000003;
region_Babelia.span.longitudeDelta = 0.1f;
region_Babelia.span.latitudeDelta = 0.1f;
[mapView setRegion:region_Babelia animated:YES];
RestMapPin *ann_Babelia = [[RestMapPin alloc] init];
ann_Babelia.title = #"Babelia";
ann_Babelia.subtitle = #"Barrio de Salamanca";
ann_Babelia.coordinate = region_Babelia.center;
[mapView addAnnotation:ann_Babelia];
/*Bacira*/
MKCoordinateRegion region_Bacira = { {0.0, 0.0}, {0.0, 0.0}};
region_Bacira.center.latitude = 40.43375390000001;
region_Bacira.center.longitude = -3.699036299999989;
region_Bacira.span.longitudeDelta = 0.1f;
region_Bacira.span.latitudeDelta = 0.1f;
[mapView setRegion:region_Bacira animated:YES];
RestMapPin *ann_Bacira = [[RestMapPin alloc] init];
ann_Bacira.title = #"Bacira";
ann_Bacira.subtitle = #"Chamberí";
ann_Bacira.coordinate = region_Bacira.center;
[mapView addAnnotation:ann_Bacira];
/*Bar Galleta*/
MKCoordinateRegion region_bar_galleta = { {0.0, 0.0}, {0.0, 0.0}};
region_bar_galleta.center.latitude = 40.4227336;
region_bar_galleta.center.longitude = -3.7036699999999882;
region_bar_galleta.span.longitudeDelta = 0.1f;
region_bar_galleta.span.latitudeDelta = 0.1f;
[mapView setRegion:region_bar_galleta animated:YES];
RestMapPin *ann_bar_galleta = [[RestMapPin alloc] init];
ann_bar_galleta.title = #"Bar Galleta";
ann_bar_galleta.subtitle = #"Malasaña";
ann_bar_galleta.coordinate = region_bar_galleta.center;
[mapView addAnnotation:ann_bar_galleta];
/*Bar Tomate*/
MKCoordinateRegion region_bar_tomate = { {0.0, 0.0}, {0.0, 0.0}};
region_bar_tomate.center.latitude = 40.428041;
region_bar_tomate.center.longitude = -3.69047;
region_bar_tomate.span.longitudeDelta = 0.1f;
region_bar_tomate.span.latitudeDelta = 0.1f;
[mapView setRegion:region_bar_tomate animated:YES];
RestMapPin *ann_bar_tomate = [[RestMapPin alloc] init];
ann_bar_tomate.title = #"Bar Tomate";
ann_bar_tomate.subtitle = #"Chamberí";
ann_bar_tomate.coordinate = region_bar_tomate.center;
[mapView addAnnotation:ann_bar_tomate];
/*Indicador de posicion del mapa (para centrarlo)*/
MKCoordinateRegion region_posicion = { {0.0, 0.0}, {0.0, 0.0}};
region_posicion.center.latitude = 40.44934744420573;
region_posicion.center.longitude = -3.695504665374756;
region_posicion.span.longitudeDelta = 0.08f;
region_posicion.span.latitudeDelta = 0.08f;
[mapView setRegion:region_posicion animated:YES];
/*************************************************/
}
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *pinView = nil;
if(annotation != mapView.userLocation) {
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"pin2#2x.png"];
}
else {
//[mapView.userLocation setTitle:#"I am here"];
}
UIButton *pinButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
if ([[annotation title] isEqualToString:#"Bacira"]) {
}
pinView.rightCalloutAccessoryView = pinButton;
return pinView;
}
-(IBAction)setMap:(id)sender {
switch (((UISegmentedControl *) sender).selectedSegmentIndex) {
case 0:
mapView.mapType = MKMapTypeStandard;
break;
case 1:
mapView.mapType = MKMapTypeSatellite;
break;
case 2:
mapView.mapType = MKMapTypeHybrid;
break;
default:
break;
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
This is my RestMapPin.h:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface RestMapPin : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#end
And this is my RestMapPin.m:
#import "RestMapPin.h"
#implementation RestMapPin
#synthesize coordinate, title, subtitle;
#end
Finally this is the view where the information of the restaurants will appear: RestViewController.h:
#import <UIKit/UIKit.h>
#import "Restaurant.h"
#interface RestViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *TitleLabel;
#property (strong, nonatomic) IBOutlet UILabel *DescriptionLabel;
#property (strong, nonatomic) IBOutlet UIImageView *ImageView;
#property (nonatomic, strong) Restaurant *DetailModal;
#end
I konw that I have to modified my viewForAnnotation method but I don't know how to do it. Than you very much for your help!
Use this delegate method for right detail button
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
RestMapPin *annView = view.annotation;
YourViewController *objYourVC= [[YourViewController alloc]init];
objYourVC.title = annView.title;
objYourVC.subtitle = annView. subtitle;
[self.navigationController pushViewController:objYourVC animated:YES];
}
As the other poster said, use the map view delegate method mapView:viewCalloutAccessoryControlTapped:.
I would avise against using the title of the annotation to look up the restaurant though. You should not use display strings to index into your data. That means that if you change a display string, or localize for another language, your lookup no longer works.
I would add an ID field to your annotations and use that.
You need to do it like this
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
RestMapPin *selectedAnnotation = view.annotation;
NSLog("Title of selected pin - %#", selectedAnnotation.title);
// Here you get the title of selected annotation
}
Now after getting the title of your selected annotation you need to create the object of RestViewController and pass the title in the variable of that controller, Same as you are doing when user select any restaurant from list.
Also, as #Duncan C mentioned in his answer, you should not use String to get the data from server, Strings can be changed.

About the Tab bar button with NSMutableArray annotation in MapKit

I have created 4 type of annotation group. In the map UI, I also added a tab bar on the bottom as my button.
My tab bar is used to filter out the annotation in MapKit.
For example... I have 4 group of annotation and 4 tab bar item.
When I clicked tab bar item 1, it show only 1 group of annotation in MapKit, other group of annotation will hide/remove in MapKit but I failed to achieve this kind of work.
My code:
in MapViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface MapViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate , UITabBarDelegate>{
IBOutlet UITabBar *tabBar;
}
#property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton;
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
my mapViewController.m:
#import "MapViewController.h"
#import "SWRevealViewController.h"
#import "Annotation.h"
#interface MapViewController ()<CLLocationManagerDelegate>
#end
//set desitination of map
#define PENANG_LATI 5.419501;
#define PENANG_LONG 100.323264;
//shop
#define SHOP_LATI 5.419501;
#define SHOP_LONG 100.323264;
//cafe
#define CAFE_LATI 5.419917;
#define CAFE_LONG 100.322969;
//food
#define FOOD_LATI 5.419746;
#define FOOD_LONG 100.322610;
//mural
#define MURAL_LATI 5.419786;
#define MURAL_LONG 100.322510;
#define THE_SPAN 0.005f;
#implementation MapViewController
#synthesize mapView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//tabBar
tabBar.delegate = self;
MKCoordinateRegion myRegion;
//Center
CLLocationCoordinate2D center;
center.latitude = PENANG_LATI;
center.longitude = PENANG_LONG;
//SPAN
MKCoordinateSpan span;
span.latitudeDelta = THE_SPAN;
span.longitudeDelta = THE_SPAN;
myRegion.center = center;
myRegion.span = span;
//set map
[mapView setRegion:myRegion animated:YES];
SWRevealViewController *revealViewController = self.revealViewController;
if ( revealViewController )
{
[self.sidebarButton setTarget: self.revealViewController];
[self.sidebarButton setAction: #selector( revealToggle: )];
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}
/*
//create coordinate
CLLocationCoordinate2D penangLocation;
penangLocation.latitude = PENANG_LATI;
penangLocation.longitude = PENANG_LONG;
Annotation * myAnnotation = [Annotation alloc];
myAnnotation.coordinate = penangLocation;
myAnnotation.title = #"THE ONE ACADEMY PENANG";
myAnnotation.subtitle = #"HELLO!! I STUDY HERE";
[self.mapView addAnnotation:myAnnotation];
*/
}
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
//my group of annotation location
NSMutableArray * myShop = [[NSMutableArray alloc] init];
NSMutableArray * myCafe = [[NSMutableArray alloc] init];
NSMutableArray * myFood = [[NSMutableArray alloc] init];
NSMutableArray * myMural = [[NSMutableArray alloc] init];
CLLocationCoordinate2D penangLocation;
Annotation * myShopAnnotation;
Annotation * myCafeAnnotation;
Annotation * myFoodAnnotation;
Annotation * myMuralAnnotation;
//shop location
myShopAnnotation = [[Annotation alloc] init];
penangLocation.latitude = SHOP_LATI;
penangLocation.longitude = SHOP_LONG;
myShopAnnotation.coordinate = penangLocation;
myShopAnnotation.title = #"Shop";
myShopAnnotation.subtitle = #"I study here";
[myShop addObject:myShopAnnotation];
//cafe location
myCafeAnnotation = [[Annotation alloc] init];
penangLocation.latitude = CAFE_LATI;
penangLocation.longitude = CAFE_LONG;
myCafeAnnotation.coordinate = penangLocation;
myCafeAnnotation.title = #"Cafe";
myCafeAnnotation.subtitle = #"I paid here";
[myCafe addObject:myCafeAnnotation];
//food location
myFoodAnnotation = [[Annotation alloc] init];
penangLocation.latitude = FOOD_LATI;
penangLocation.longitude = FOOD_LONG;
myFoodAnnotation.coordinate = penangLocation;
myFoodAnnotation.title = #"Food";
myFoodAnnotation.subtitle = #"I walk here";
[myFood addObject:myFoodAnnotation];
//Mural location
myMuralAnnotation = [[Annotation alloc] init];
penangLocation.latitude = MURAL_LATI;
penangLocation.longitude = MURAL_LONG;
myMuralAnnotation.coordinate = penangLocation;
myMuralAnnotation.title = #"Mural";
myMuralAnnotation.subtitle = #"I walk here";
[myMural addObject:myMuralAnnotation];
if(item.tag == 1)
{
//show and hide annotation
NSLog(#"shop");
[mapView addAnnotations:myShop];
[mapView removeAnnotations:myCafe];
[mapView removeAnnotations:myFood];
[mapView removeAnnotations:myMural];
}
if(item.tag == 2)
{
//show and hide annotation
NSLog(#"cafe");
[mapView removeAnnotations:myShop];
[mapView addAnnotations:myCafe];
[mapView removeAnnotations:myFood];
[mapView removeAnnotations:myMural];
}
if(item.tag == 3)
{
//show and hide annotation
NSLog(#"food");
[mapView removeAnnotations:myShop];
[mapView removeAnnotations:myCafe];
[mapView removeAnnotations:myFood];
[mapView addAnnotations:myMural];
}
if(item.tag == 4)
{
//show and hide annotation
NSLog(#"mural");
[mapView removeAnnotations:myShop];
[mapView removeAnnotations:myCafe];
[mapView removeAnnotations:myFood];
[mapView addAnnotations:myMural];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
When removeAnnotations: is called like this:
[mapView removeAnnotations:myCafe];
the map view looks for the exact objects (using pointer comparison) in myCafe that are already on the map.
The map view here does not match up annotations using their coordinate, title, etc.
Since the code creates new instances of each annotation every time a selection is made, the new instances are not found on the map and so removeAnnotations: does nothing.
Instead, in your case, you could just tell the map view to remove all existing annotations and then add the new annotations based on the current selection.
Instead of this:
[mapView addAnnotations:myShop];
[mapView removeAnnotations:myCafe];
[mapView removeAnnotations:myFood];
[mapView removeAnnotations:myMural];
do this:
[mapView removeAnnotations:mapView.annotations]; //remove all
[mapView addAnnotations:myShop]; //then add new
The code could be simplified as well by using a switch statement and in each case, only create the annotations needed for the selection (you don't need to create all annotations every time).

Using AVSpeechSynthesizer to read a description of location on a Map

My map has 4 or 5 points close to each other and right now using AVSpeechSynthesizer I've got it so that it will say the name of the location (which is also displayed in a little bubble).
I want it to still show that bubble but when clicked I want it to say a description of that place that I would have specified. This is my code at the moment:
MapViewAnnotation.h
#interface MapViewAnnotation : NSObject <MKAnnotation> {
NSString *title;
CLLocationCoordinate2D coordinate;
NSString *desc;
}
#property (nonatomic, copy) NSString *title;
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, readonly) NSString *desc;
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d initWithDesc:(NSString *)dsc;
MapViewAnnotation.m
#implementation MapViewAnnotation
#synthesize title, coordinate, desc;
- (id)initWithTitle:(NSString *)ttl andCoordinate:(CLLocationCoordinate2D)c2d initWithDesc:(NSString *)dsc {
[super init];
title = ttl;
coordinate = c2d;
desc = dsc;
return self;
MapViewController.h
#interface MapViewController : UIViewController {
MKMapView *mapView;
}
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
#property (strong, nonatomic) AVSpeechSynthesizer *synthesizer;
MapViewController.m
- (void)viewDidLoad
{
// Set some coordinates for our position : Cutty Sark
CLLocationCoordinate2D location;
location.latitude = (double) 51.482997;
location.longitude = (double) -0.010072;
// Royal Observatory
CLLocationCoordinate2D twoLocation;
twoLocation.latitude = (double) 51.477805;
twoLocation.longitude = (double) -0.001430;
//Royal Naval College
CLLocationCoordinate2D threeLocation;
threeLocation.latitude = (double) 51.483344;
threeLocation.longitude = (double) -0.006799;
//Queen's House
CLLocationCoordinate2D fourLocation;
fourLocation.latitude = (double) 51.481383;
fourLocation.longitude = (double) -0.003722;
//National Maritime Museum
CLLocationCoordinate2D fiveLocation;
fiveLocation.latitude = (double) 51.481050;
fiveLocation.longitude = (double) -0.005578;
// Add Cutty Sark annotation to MapView
MapViewAnnotation *newAnnotation = [[MapViewAnnotation alloc] initWithTitle:#"Cutty Sark" andCoordinate:location initWithDesc:#"Description about Cutty Sark"];
[self.mapView addAnnotation:newAnnotation];
self.mapView.delegate = self;
[newAnnotation release];
// Add Royal Observatory annotation to MapView
newAnnotation = [[MapViewAnnotation alloc] initWithTitle:#"Royal Observatory" andCoordinate:twoLocation initWithDesc:#"Description about Cutty Sark"];
[self.mapView addAnnotation:newAnnotation];
[newAnnotation release];
// Add Royal Naval College annotation to MapView
newAnnotation = [[MapViewAnnotation alloc] initWithTitle:#"Royal Naval College" andCoordinate:threeLocation initWithDesc:#"Description about Cutty Sark"];
[self.mapView addAnnotation:newAnnotation];
[newAnnotation release];
// Add Queen's House annotation to MapView
newAnnotation = [[MapViewAnnotation alloc] initWithTitle:#"Queen's House" andCoordinate:fourLocation initWithDesc:#"Description about Cutty Sark"];
[self.mapView addAnnotation:newAnnotation];
[newAnnotation release];
// Add National Maritime Museum annotation to MapView
newAnnotation = [[MapViewAnnotation alloc] initWithTitle:#"National Maritime Museum" andCoordinate:fiveLocation initWithDesc:#"Description about Cutty Sark"];
[self.mapView addAnnotation:newAnnotation];
[newAnnotation release];
}
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)anView
{
AVSpeechSynthesizer *synthesizer = [[AVSpeechSynthesizer alloc]init];
AVSpeechUtterance *utterance = [AVSpeechUtterance speechUtteranceWithString:((MapViewAnnotation *)anView).desc];
[utterance setRate:0.5];
[synthesizer speakUtterance:utterance];
}
// When a map annotation point is added, zoom to it (1500 range)
- (void)mapView:(MKMapView *)mv didAddAnnotationViews:(NSArray *)views
{
MKAnnotationView *annotationView = [views objectAtIndex:0];
id <MKAnnotation> mp = [annotationView annotation];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance([mp coordinate], 1500, 1500);
[mv setRegion:region animated:YES];
//[mv selectAnnotation:mp animated:YES];
}
Any help would be appreciated!
EDIT
Here is the NSLog:
In the didSelectAnnotationView delegate method, the anView parameter is the MKAnnotationView.
That is, anView is the view (MKAnnotationView or MKPinAnnotationView class) object of the annotation.
It is not the model (your MapViewAnnotation class) object of the annotation.
To refer to the annotation model instance that the view is for, use the view's annotation property and cast it to your class:
- (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)anView
{
//Get a reference to the annotation this view is for...
id<MKAnnotation> annSelected = anView.annotation;
//Before casting, make sure this annotation is our custom type
//(and not some other type like MKUserLocation)...
if ([annSelected isKindOfClass:[MapViewAnnotation class]])
{
MapViewAnnotation *mva = (MapViewAnnotation *)annSelected;
AVSpeechSynthesizer *synthesizer = [[AVSpeechSynthesizer alloc]init];
AVSpeechUtterance *utterance =
[AVSpeechUtterance speechUtteranceWithString:mva.desc];
[utterance setRate:0.5];
[synthesizer speakUtterance:utterance];
}
}

How can I add different images instead of pins in MKMapView?

I've been working on an app that has an MKMapView and I want to customize the pins with different images. I've already did that but with one image only, now I need to make a pin show an image and the other pin show another image. How can I do this? If helps, here's my code:
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation{
MKAnnotationView *pinView = nil;
if(annotation != _mapView.userLocation)
{
static NSString *defaultPinID;
pinView = (MKAnnotationView *)[_mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"image1.jpg"];
}
else {
[_mapView.userLocation setTitle:#"Your Location"];
}
return pinView; }
I need the second and the third to show the same image but the first a different one
It follows like this:
- (void)viewWillAppear:(BOOL)animated {CLLocationCoordinate2D First; First.latitude = -12.098970; First.longitude = -77.034531; MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc] init]; annotationPoint.coordinate = First; annotationPoint.title = #"First"; annotationPoint.subtitle = #"Subtitle1"; [_mapView addAnnotation:annotationPoint];
CLLocationCoordinate2D Second; Second.latitude = -12.098299; Second.longitude = -77.068364; MKPointAnnotation *annotationPoint2 = [[MKPointAnnotation alloc] init]; annotationPoint2.coordinate = Second; annotationPoint2.title = #"Second"; annotationPoint2.subtitle = #"Subtitle2"; [_mapView addAnnotation:annotationPoint2];
CLLocationCoordinate2D Third; Third.latitude = -12.125888; Third.longitude = -77.023346; MKPointAnnotation *annotationPoint3 = [[MKPointAnnotation alloc] init]; annotationPoint3.coordinate = Third; annotationPoint3.title = #"Third"; annotationPoint3.subtitle = #"Subtitle3"; [_mapView addAnnotation:annotationPoint3];}
Make sure you have MapKit.framework and CoreLocation.framework in your project.
My custom pin images are 39 high by 32 wide. Have not tried other sizes but feel free to experiment. My 2 pin images are called pin1.png and pin2.png
Make sure you have your images named correctly to match what is in your code.
In my example I am not using current location but rather a static custom location (thought The Bahamas would be nice for this example). In your project you would of course you the Location Manager to get a user's current location.
I have tested my example and have successfully dropped 2 pins on the map with each pin having its own custom image.
It's not the cleanest code but I only had limited time to write it.
Here is the code for ViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate>
#end
Here is the code for ViewController.h
#import "ViewController.h"
#import "MyAnnotation.h"
#import <MapKit/MapKit.h>
#interface ViewController ()
#property (strong, nonatomic) IBOutlet MKMapView *myMapView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// setup the map view, delegate and current location
[self.myMapView setDelegate:self];
self.myMapView.mapType = MKMapTypeStandard;
CLLocationCoordinate2D myLocation = CLLocationCoordinate2DMake(25.085130,-77.331428);
[self.myMapView setCenterCoordinate:myLocation];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(myLocation, 2000, 2000);
region.center = self.myMapView.centerCoordinate;
self.myMapView.showsUserLocation = YES;
[self.myMapView setRegion:region animated:YES];
[self dropPins];
}
-(void)dropPins {
NSMutableArray *annotationArray = [[NSMutableArray alloc] init];
CLLocationCoordinate2D location1 = CLLocationCoordinate2DMake(25.085130, -77.331428);
MyAnnotation *annotation1 = [[MyAnnotation alloc] initWithCoordinates:location1 image:#"pin1.png"];
[annotationArray addObject:annotation1];
[self.myMapView addAnnotations:annotationArray];
[annotationArray removeAllObjects];
CLLocationCoordinate2D location2 = CLLocationCoordinate2DMake(25.085130, -77.336428);
MyAnnotation *annotation2 = [[MyAnnotation alloc] initWithCoordinates:location2 image:#"pin2.png"];
[annotationArray addObject:annotation2];
[self.myMapView addAnnotations:annotationArray];
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
static NSString *identifier = #"MyLocation";
if ([annotation isKindOfClass:[MyAnnotation class]])
{
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[self.myMapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil)
{
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
} else
{
annotationView.annotation = annotation;
}
annotationView.enabled = YES;
annotationView.canShowCallout = NO;
if([[(MyAnnotation *)annotationView.annotation image] isEqualToString:#"pin1.png"])
annotationView.image = [UIImage imageNamed:#"pin1.png"];
if([[(MyAnnotation *)annotationView.annotation image] isEqualToString:#"pin2.png"])
annotationView.image = [UIImage imageNamed:#"pin2.png"];
return annotationView;
}
return nil;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Here is the code for MyAnnotation.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MyAnnotation : NSObject <MKAnnotation>
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy, readonly) NSString *image;
-(id)initWithCoordinates:(CLLocationCoordinate2D) paramCoordinates
image:(NSString *) paramImage;
#end
Here is the code for MyAnnotation.m
#import "MyAnnotation.h"
#implementation MyAnnotation
-(id)initWithCoordinates:(CLLocationCoordinate2D)paramCoordinates
image:(NSString *)paramImage
{
self = [super init];
if(self != nil)
{
_coordinate = paramCoordinates;
_image = paramImage;
}
return (self);
}
#end

Resources