A little bit tired cause limitations of built-in Google Maps control. It’s good chance to write some samples of using alternatives.
- Route me
- BSD licensed open source. It’s up to you if it’s an advantage
- Support lots of sources: OpenStreetMap, Microsoft Virtual Earth, Cloud Made and even old school Yahoo Maps and some other less popular
- Formed discussing community – Google Group
- Cloud Made
- Piece of larger project, so officially has support team and potentially better integration with Cloud Made maps
- I use it at very early stage, so not sure of current quality
- Has tons of cool themes for maps
- Open xCode and create new project. I chose View-Based Application and named “RouteMeSourceSelection”.
- Download actual Route Me sources
- Setup Route Me control very accurately step by step with the Embedding Guide
Open UIViewController header file (mine is “RouteMeSourceSelectionViewController.h”) and:
- #import “RMMapView.h”
- add protocol “RMMapViewDelegate”
- create IBOutlet RMMapView *mapView;
- (void)viewDidLoad { [super viewDidLoad]; [RMMapView class]; // this important, maps won't display without it [mapView setDelegate:self];}
Now run the project and you will see the maps with default Open Street View source.
All that were really easy. Now give a user possibility to select map source from UIPickerView.
Map source UIPickerView (code)
Open the controller header file and add protocols UIPickerViewDelegate and UIPickerViewDataSource, then add and several IBOutlets:
#import #import "RMMapView.h" @interface RouteMeSourceSelectionViewController : UIViewController<rmmapviewdelegate, uipickerviewdatasource="" uipickerviewdelegate,="">{ IBOutlet RMMapView *mapView; IBOutlet UIPickerView *mapSourcePicker; IBOutlet UIBarButtonItem *mapSettingsBarButton;} - (IBAction) showMapsSettings; @end
static NSArray *titles = nil; - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{ return [titles objectAtIndex:row];} - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{ if (!titles) { titles = [[NSArray alloc] initWithObjects: @"Open Street Maps", @"Yahoo Map", @"Virtual Earth Aerial", @"Virtual Earth Hybrid", @"Virtual Earth Road", @"Cloud Made Map", nil]; } return [titles count];} - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{ return 1;}
Make showMapsSettings method to show/hude the UIPickerView and set some UI trifles:
- (IBAction) showMapsSettings{ BOOL toShow = [mapSourcePicker isHidden]; if (toShow) { [mapSettingsBarButton setStyle:UIBarButtonItemStyleDone]; } else // hidding { [mapSettingsBarButton setStyle:UIBarButtonItemStyleBordered]; [self setMapSourceWithNumber:[mapSourcePicker selectedRowInComponent:0]]; } [mapSourcePicker setHidden:![mapSourcePicker isHidden]]; [mapView setUserInteractionEnabled:[mapSourcePicker isHidden]];}
And the main part is to change map source of the mapView object:
#import "RMVirtualEarthSource.h"#import "RMYahooMapSource.h"#import "RMCloudMadeMapSource.h"#import "RMOpenStreetMapsSource.h" #define CONST_MAP_KEY_bing @""#define CONST_MAP_KEY_cloud @"" - (void) setMapSourceWithNumber:(int)number{ if (mapSourceNumber == number) return; switch (number) { case 0: mapView.contents.tileSource = [[RMOpenStreetMapsSource alloc] init]; break; case 1: mapView.contents.tileSource = [[RMYahooMapSource alloc] init]; break; case 2: mapView.contents.tileSource = [[RMVirtualEarthSource alloc] initWithAerialThemeUsingAccessKey:CONST_MAP_KEY_bing]; break; case 3: mapView.contents.tileSource = [[RMVirtualEarthSource alloc] initWithHybridThemeUsingAccessKey:CONST_MAP_KEY_bing]; break; case 4: mapView.contents.tileSource = [[RMVirtualEarthSource alloc] initWithRoadThemeUsingAccessKey:CONST_MAP_KEY_bing]; break; case 5: mapView.contents.tileSource = [[RMCloudMadeMapSource alloc] initWithAccessKey:CONST_MAP_KEY_cloud styleNumber:1]; break; default: return; break; } // this trick refreshs maps with new source [mapView moveBy:CGSizeMake(640,960)]; [mapView moveBy:CGSizeMake(-640,-960)]; mapSourceNumber = number; // remember user choice between runnings [[NSUserDefaults standardUserDefaults] setInteger:mapSourceNumber forKey:@"mapSourceNumber"];}
To obtain developer API key for Cloud Made and Virtual Earth (Bing) you need to register and submit a form:
The last thing I want to add is to remember what user chose during last app using. Let’s modify a viewDidLoad to:
- (void)viewDidLoad { [super viewDidLoad]; [RMMapView class]; [mapView setDelegate:self]; int number = [[NSUserDefaults standardUserDefaults] integerForKey:@"mapSourceNumber"]; [self setMapSourceWithNumber:number]; [mapSourcePicker selectRow:mapSourceNumber inComponent:0 animated:NO];}
Note, selected map source number is stored to standartUserDefaults at end of setMapSourceWithNumber.
Map source UIPickerView (design)
Open IB to add:
- UIToolbar with one UIBarButtonItem connected to its IBOutlet
- connect an UIBarButtonItem press event with showMapsSettings IBAction
- UIPickerView above the map view and set it hidden
- then connect an UIPickerView with IBOutlet and set its delegate and dataSource to the file’s owner
If you did all right and I did not forget something to describe you should have working app. Please run you application and campare to mine:
This sample is a part of my real application - Meeting Point. It’s free to download, try it.







Place your comment