I am displaying the google map using Google Maps SDK for iOS. When I start the view controller first time it shows the map fine. But when I goto the view controller second time it does not display the google map. It shows the blank screen. Actually I am passing the address in the google geo coding api from there I am getting the lang & lat then I am displaying the google map.
Code for displaying google map
//
// GmapViewController.m
// MyDex
// Created by Admin on 8/18/15.
// Copyright (c) 2015 com.vastedge. All rights reserved.
#import "GmapViewController.h"
#import "AFNetworking.h"
#import "UIKit+AFNetworking.h"
#import GoogleMaps;
#interface GmapViewController ()
#end
#implementation GmapViewController
{
GMSMapView *mapView_;
NSString *lat;
NSString *lng;
CLLocationDegrees latitude;
CLLocationDegrees longitude;
UIActivityIndicatorView *activityView;
}
-(void)geoCodeAddress
{
NSCharacterSet *doNotWant = [NSCharacterSet characterSetWithCharactersInString:#":/,."];
self.address = [[self.address componentsSeparatedByCharactersInSet: doNotWant] componentsJoinedByString: #""];
NSString *urlString=[NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/geocode/json?address=%#",self.address];
urlString = [urlString stringByAddingPercentEscapesUsingEncoding:
NSUTF8StringEncoding];
AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc] initWithBaseURL:[NSURL URLWithString:urlString]];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
AFHTTPRequestOperation *operation = [manager GET:urlString parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject)
{
NSArray * results = [responseObject objectForKey:#"results"];
NSDictionary *records=[results objectAtIndex:0];
NSDictionary *geometry=[records objectForKey:#"geometry"];
NSLog(#"geomatry is %#",geometry);
NSDictionary *latLong=[geometry objectForKey:#"location"];
lat=[latLong objectForKey:#"lat"];
lng=[latLong objectForKey:#"lng"];
latitude=[lat floatValue];
longitude=[lng floatValue];
NSLog(#"main lat is %f",latitude);
NSLog(#"main lng is %f",longitude);
[self activityIndicator:#"hide"];
[self Loadgmap];
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"failure string is");
[self activityIndicator:#"hide"];
UIAlertView *alert =[[UIAlertView alloc]initWithTitle:#"Warning" message:#"Unable to display map" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
}];
[operation start];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self activityIndicator:#"show"];
[self geoCodeAddress];
}
-(void)Loadgmap
{
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.868
longitude:151.2086
zoom:6];
GMSMapView *mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = camera.target;
marker.snippet = #"Hello World";
marker.appearAnimation = kGMSMarkerAnimationPop;
marker.map = mapView;
self.view = mapView;
}
-(void)activityIndicator:(NSString *)show
{
if([show isEqual:#"show"])
{
NSLog(#"loading shown");
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
activityView.layer.backgroundColor = [[UIColor colorWithWhite:0.0f alpha:0.5f] CGColor];
activityView.hidesWhenStopped = YES;
activityView.frame = self.view.bounds;
[self.view addSubview:activityView];
[activityView startAnimating];
}
else
{
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
[activityView stopAnimating];
[activityView removeFromSuperview];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
Using dispatch_async(dispatch_get_main_queue(), ^{}) is a better practice, but the main problem of your white screen issue is the view in your ViewController get assigned to new value twice.
When the [self Loadgmap] is called in you viewDidLoad(), the self.view = mapView; is called. When your networking required is done, your [self Loadgmap] is called again, and the self.view = mapView; is called again, which make your view become a white screen.
You should only assign value to your view in the viewDidLoad() method, not later in other method calls.
To fix your problem, you can make a new method call -(void)updateMap():
-(void)updateMap {
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:[lat floatValue]
longitude:[lng floatValue]
zoom:6];
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = camera.target;
marker.snippet = #"Hello World";
marker.appearAnimation = kGMSMarkerAnimationPop;
marker.map = (GMSMapView*)self.view;
[((GMSMapView*)self.view) animateToCameraPosition:camera];
}
You should call it inside your network request success block:
NSArray * results = [responseObject objectForKey:#"results"];
NSDictionary *records=[results objectAtIndex:0];
NSDictionary *geometry=[records objectForKey:#"geometry"];
NSLog(#"geomatry is %#",geometry);
NSDictionary *latLong=[geometry objectForKey:#"location"];
lat=[latLong objectForKey:#"lat"];
lng=[latLong objectForKey:#"lng"];
latitude=[lat floatValue];
longitude=[lng floatValue];
NSLog(#"main lat is %f",latitude);
NSLog(#"main lng is %f",longitude);
dispatch_async(dispatch_get_main_queue(), ^{
[self activityIndicator:#"hide"];
[self updateMap];
});
Your viewDidLoad() should call [self Loadgmap] first to initialize a Google Map to your view.
- (void)viewDidLoad
{
[super viewDidLoad];
[self activityIndicator:#"show"];
[self Loadgmap];
[self geoCodeAddress];
}
Full code snippet: https://gist.github.com/ziyang0621/f66dd536382b1b16597d
Related
I am trying to add drag and drop functionality on Google map. Overall it is done but one thing has to fix. That is when I drag and drop GMSMarker on Google map pervious GMSMarker still exist and another (wherever I dropped it) GMSMarker created new. But I want only one GMSMarker. How to remove pervious/ old GMSMarker. Any suggestion will be Great. Thanks in advance.
Code :
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
// Mumbabi address
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:19.01761470
longitude:72.85616440
zoom:4];
// mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
mapViewGMS.camera=camera;
mapViewGMS.delegate = self;
CLLocationCoordinate2D position = CLLocationCoordinate2DMake([#"19.01761470" floatValue ], [#"72.85616440" floatValue]);
GMSMarker *marker = [GMSMarker markerWithPosition:position];
marker.title = #"This is your current location";
[marker setDraggable: YES];
marker.appearAnimation=0.2f;
marker.map = mapViewGMS;
}
- (void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker
{
NSLog(#">>> mapView:didEndDraggingMarker: %#", [marker description]);
NSString *lati=[NSString stringWithFormat:#"%f",marker.position.latitude];
NSString *longi=[NSString stringWithFormat:#"%f",marker.position.longitude];
NSString * urpPath = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?latlng=%#,%#&sensor=true",lati,longi];
[[ConnectionManager connectionManagerSharedInstance]sendPOSTRequestForPath:urpPath data:nil timeoutInterval:50 completion:^(NSDictionary *dictionary, NSError *error) {
if(!error){
if(dictionary){
if([dictionary valueForKey:#"results"] == nil || [[dictionary valueForKey:#"status"]isEqualToString:#"ZERO_RESULTS"]){
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:[ViewUtilities showAlert:#"Message!!" :#"Unable to fetch this location, May be this is an invalid loation. However Please Check your Internet Connection, and re- run this app."] animated:YES completion:nil];
});
}
else
{
strUserCurrentAddressAuto=[NSString stringWithFormat:#"%#",[[[dictionary valueForKey:#"results"] objectAtIndex:0] valueForKey:#"formatted_address"]];
NSLog(#"\n\n ***** Great User address found,---> %# *****\n\n",strUserCurrentAddressAuto);
dispatch_async(dispatch_get_main_queue(), ^{
//[self.automaticallySearchBtn setTitle:self.fullSourceAddress forState:UIControlStateNormal];
UIAlertController *alert= [UIAlertController alertControllerWithTitle:strUserCurrentAddressAuto message:#"Select this Loaction for ?"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *pick = [UIAlertAction actionWithTitle:#"Pick Up Location" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
labelSourceLocation.text=strUserCurrentAddressAuto;
// nil marker title (old title it is : This is your current location)
marker.title = nil;
locationSource = [[CLLocation alloc] initWithLatitude:marker.position.latitude longitude:marker.position.longitude];
if (locationSource !=nil && locationDest!=nil) {
CLLocationDistance dist = [locationSource distanceFromLocation:locationDest]/1000;
NSLog(#"\n\n **** Using Drag and drop Poin, Total distance in K.M. => %f",dist);
totalDistance = [NSString stringWithFormat:#"%f",dist];
}
[alert dismissViewControllerAnimated:YES completion:nil];
}];
UIAlertAction *drop = [UIAlertAction actionWithTitle:#"Drop Location" style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
labelDropLocation.text=strUserCurrentAddressAuto;
// nil marker title (old title it is : This is your current location)
marker.title = nil;
locationDest = [[CLLocation alloc] initWithLatitude:marker.position.latitude longitude:marker.position.longitude];
if (locationSource !=nil && locationDest!=nil) {
CLLocationDistance dist = [locationSource distanceFromLocation:locationDest]/1000;
NSLog(#"\n\n **** Using Drag and drop Poin, Total distance in K.M. => %f",dist);
totalDistance = [NSString stringWithFormat:#"%f",dist];
}
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:pick];
[alert addAction:drop];
[self presentViewController:alert animated:YES completion:nil];
});
}
}
}
}];
}
You need to remove the previous marker placed over mapView, it is the most preferable solution in this kind of situation or accordingly.
To Clear mapView:
[mapView clear];
Use below code to drag and drop marker excluding previous one:
-(void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker{
CLLocationCoordinate2D pos;
pos.latitude = marker.position.latitude;
pos.longitude = marker.position.longitude;
// this removes the previous markers
[mapView clear];
// this method adds the marker where user dropped it
[self placeMarker:pos.latitude withLong:pos.longitude];
}
// helping method
-(void) placeMarker:(float)lat withLong:(float)lon{
CLLocationCoordinate2D pinlocation;
pinlocation.latitude = lat;
pinlocation.longitude = lon;
GMSMarker *marker = [[GMSMarker alloc] init];
[marker setDraggable: YES];
marker.position = pinlocation;
marker.title = #"Hi";
marker.snippet = #"New marker";
marker.appearAnimation = kGMSMarkerAnimationPop;
marker.icon = [GMSMarker markerImageWithColor:[UIColor redColor]];
marker.map = self.mapView;
// this always visible marker info window, comment if do not need
[self.mapView setSelectedMarker:marker];
}
Update:
To remove specific marker on map, just keep the reference of that marker object and later set it to nil see below code:
// declare marker globally to declare its scope to entire class.
GMSMarker *markerToRemoveLater;
// initialization and configuration
markerToRemoveLater = [[GMSMarker alloc] init];
// set nil where you want to remove specific marker
markerToRemoveLater.map = nil;
I had the same issue when I was working on Gmaps. I wanted to clear the marker without using [map clear]. I came up with this solution.
-(void)mapView:(GMSMapView *)mapView didEndDraggingMarker:(GMSMarker *)marker{
CLLocationCoordinate2D pos;
pos.latitude = marker.position.latitude;
pos.longitude = marker.position.longitude;
// this removes the previous marker from map
marker.map = nil;
// ** Give your marker new position from CLLocationCoordinate2D
//Then
[self mapView:mapViewGoog didTapAtCoordinate:marker.position];
}
- (void)mapView:(GMSMapView *)mapView didTapAtCoordinate:(CLLocationCoordinate2D)coordinate {
[self addMarkerInTheMapView:coordinate];
}
-(void)addMarkerInTheMapView:(CLLocationCoordinate2D)coordinate{
markerMYLocation.map = nil;
markerMYLocation = [[GMSMarker alloc] init];
//Your code here.
markerMYLocation.map = mapView;
}
I'm making a rest call and returning lat longs with the call. For now I just return the coords passed because im just trying to learn the workings of objective C and iphone programing its been a few years. I have some code currently where I define some public vars that I set with in my rest function but when I go to draw them on a map they are 0 but if i break inside the function where im setting the label.text elements to the values they are set to the correct value but when it finishes the rest call they are reset. Not sure why
//
// ViewController.m
// REST
//
// Created by Grant Zukel on 8/5/15.
// Copyright © 2015 Grant Zukel. All rights reserved.
//
#import "ViewController.h"
#import GoogleMaps;
#interface ViewController ()
{
}
#end
#implementation ViewController{
GMSMapView *mapView_;
#public NSInteger int_lat;
#public NSInteger int_lon;
}
- (IBAction)drawMap;
{
NSURL *url = [NSURL URLWithString:#"http://127.0.0.1:8001/test/39.748922&-104.986147"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data, NSError *connectionError)
{
if (data.length > 0 && connectionError == nil)
{
NSDictionary *greeting = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
//NSLog([greeting objectForKey:#"status"]);
self.greetingContent.text = [greeting objectForKey:#"content"];
self.greetingId.text = [greeting objectForKey:#"id"];
NSString *latitude = ([[greeting objectForKey:#"coords"] objectForKey:#"latitude"]);
NSString *longitude = ([[greeting objectForKey:#"coords"] objectForKey:#"longitude"]);
self.testLat.text = latitude;
self.testLon.text = longitude;
int_lat = [latitude intValue];
int_lon = [longitude intValue];
}
}];
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:int_lat
longitude:int_lon
zoom:1];
mapView_ = [GMSMapView mapWithFrame:CGRectZero camera:camera];
mapView_.myLocationEnabled = YES;
self.view = mapView_;
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(int_lat, int_lon);
marker.title = #"Test";
marker.snippet = #"Test";
marker.map = mapView_;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self drawMap];
//NSString *temperatureString = [self getStringForTemperature:A base:B];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Hi in my application I have integrated google map now i want to give navigation direction from my current location to destination point please tell me how to achieve this one.
My code.
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:12.9259
longitude:77.6229
zoom:6];
mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
mapView.myLocationEnabled= NO;
self.view = mapView;
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(12.9259, 77.6229);
marker.title = #"Hello World";
marker.snippet = #"bangalore";
marker.map = mapView;
The above code i have used to point maker of my destination point in that please tell me how to add the navigation direction to that i have been stuck here for long time please help me out.
Thanks.
You can use either the comgooglemaps:// or comgooglemaps-x-callback:// URL schemes.
Note: Buttons added via the x-source parameter will not be displayed in the turn-by-turn navigation UI.
The below code snippet shows how to use the comgooglemaps-x-callback:// scheme to request directions, and then return to your app when your user is ready. The code will do the following:
Verify that the comgooglemaps-x-callback:// URL scheme is available.
Launch the Google Maps for iOS app, and request directions to JFK Airport in New York city. Leave the start address blank to request directions from the user's current location.
Add a button labelled "AirApp" to the Google Maps for iOS App. The button label is defined by the x-source parameter.
Call the fictitious URL scheme, sourceapp://, when the users clicks the back button.
The code is shown below.
NSURL *testURL = [NSURL URLWithString:#"comgooglemaps-x-callback://"];
if ([[UIApplication sharedApplication] canOpenURL:testURL]) {
NSString *directionsRequest = #"comgooglemaps-x-callback://" +
#"? daddr=John+F.+Kennedy+International+Airport,+Van+Wyck+Expressway,+Jamaica,+New+York" +
#"&x-success=sourceapp://?resume=true&x-source=AirApp";
NSURL *directionsURL = [NSURL URLWithString:directionsRequest];
[[UIApplication sharedApplication] openURL:directionsURL];
}
else
{
NSLog(#"Can't use comgooglemaps-x-callback:// on this device.");
}
Go with this answer..
- (IBAction)handleRoutePressed:(id)sender {
// We're working
self.activityIndicator.hidden = NO;
[self.activityIndicator startAnimating];
self.routeButton.enabled = NO;
self.routeDetailsButton.enabled = NO;
// Make a directions request
MKDirectionsRequest *directionsRequest = [MKDirectionsRequest new];
// Start at our current location
MKMapItem *source = [MKMapItem mapItemForCurrentLocation];
[directionsRequest setSource:source];
// Make the destination
CLLocationCoordinate2D destinationCoords = CLLocationCoordinate2DMake(38.8977, -77.0365);
MKPlacemark *destinationPlacemark = [[MKPlacemark alloc] initWithCoordinate:destinationCoords addressDictionary:nil];
MKMapItem *destination = [[MKMapItem alloc] initWithPlacemark:destinationPlacemark];
[directionsRequest setDestination:destination];
MKDirections *directions = [[MKDirections alloc] initWithRequest:directionsRequest];
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
// We're done
self.activityIndicator.hidden = YES;
[self.activityIndicator stopAnimating];
self.routeButton.enabled = YES;
// Now handle the result
if (error) {
NSLog(#"There was an error getting your directions");
return;
}
// So there wasn't an error - let's plot those routes
self.routeDetailsButton.enabled = YES;
self.routeDetailsButton.hidden = NO;
_currentRoute = [response.routes firstObject];
[self plotRouteOnMap:_currentRoute];
}];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController isKindOfClass:[SCStepsViewController class]]) {
SCStepsViewController *vc = (SCStepsViewController *)segue.destinationViewController;
vc.route = _currentRoute;
}
}
#pragma mark - Utility Methods
- (void)plotRouteOnMap:(MKRoute *)route
{
if(_routeOverlay) {
[self.mapView removeOverlay:_routeOverlay];
}
// Update the ivar
_routeOverlay = route.polyline;
// Add it to the map
[self.mapView addOverlay:_routeOverlay];
}
#pragma mark - MKMapViewDelegate methods
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay: (id<MKOverlay>)overlay
{
MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
renderer.strokeColor = [UIColor redColor];
renderer.lineWidth = 4.0;
return renderer;
}
If u dont want to use NSURL then you can simply use[MKMapItem openMapsWithItems:]
- (void)openMapsWithDirectionsTo:(CLLocationCoordinate2D)to {
Class itemClass = [MKMapItem class];
if (itemClass && [itemClass res pondsToSelector:#selector(openMapsWithItems:launchOptions:)]) {
MKMapItem *currentLocation = [MKMapItem mapItemForCurrentLocation];
MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[[MKPlacemark alloc] initWithCoordinate:to addressDictionary:nil] autorelease]];
toLocation.name = #"Destination";
[MKMapItem openMapsWithItems:[NSArray arrayWithObjects:currentLocation, toLocation, nil]
launchOptions:[NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:MKLaunchOptionsDirectionsModeDriving, [NSNumber numberWithBool:YES], nil]
forKeys:[NSArray arrayWithObjects:MKLaunchOptionsDirectionsModeKey, MKLaunchOptionsShowsTrafficKey, nil]]];
[toLocation release];
}
else {
NSMutableString *mapURL = [NSMutableString stringWithString:#"http://maps.google.com/maps?"];
[mapURL appendFormat:#"saddr=Current Location"];
[mapURL appendFormat:#"&daddr=%f,%f", to.latitude, to.longitude];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[mapURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
}
}
I am using the latest GoogleMaps iOS SDK in my application and after the latest iOS update, 7.0.3, it started becoming unresponsive after first touch. Let me expand on this. After the first touch on the map, the map becomes unresponsive. At first, you can pinch zoom, drag, swipe, and everything else but after that first touch, it no longer works. This started happening after Apple updated their iOS. If I use the iOS6 simulator, I can can do all the gestures even after the first touch. I don't know if this is because of the iOS update or something is wrong with my code. If anyone has any suggestions or has gone through something like this that could guide me, that could be greatly appreciated. Thanks in advance.
Followed the website instructions here: (https://developers.google.com/maps/documentation/ios/start#adding_the_google_maps_sdk_for_ios_to_your_project)
and it works on iOS6 and was working on iOS7 before.
MapsViewController.m
#import "MapsViewController.h"
#import <GoogleMaps/GoogleMaps.h>
#interface MapsViewController ()
#end
#implementation MapsViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.storeNamesArray = [[NSMutableArray alloc] init];
self.storePricesArray = [[NSMutableArray alloc] init];
self.storeLatitudeArray = [[NSMutableArray alloc] init];
self.storeLongitudeArray = [[NSMutableArray alloc] init];
self.priceTypeArray = [[NSMutableArray alloc] init];
dispatch_async(dispatch_get_main_queue(), ^{ NSData *data =
[NSData dataWithContentsOfURL:[NSURL URLWithString:
[NSString stringWithFormat: #"http://www.someurl.com/mobile-api"]]];
[self performSelectorOnMainThread:#selector(fetchData:) withObject:data
waitUntilDone:YES]; });
}
-(void)fetchData:(NSData *)responseData
{
if (responseData)
{
NSError *error;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
NSDictionary *stores =[json objectForKey:#"stores"];
for(NSDictionary *location in stores)
{
[self.storeNamesArray addObject:[location objectForKey:#"name"]];
[self.storePricesArray addObject:[location objectForKey:#"price"]];
[self.storeLatitudeArray addObject:[location objectForKey:#"latitude"]];
[self.storeLongitudeArray addObject:[location objectForKey:#"longitude"]];
[self.priceTypeArray addObject:[location objectForKey:#"price_type"]];
}
}
double lat = 0.0;
double lon = 0.0;
GMSCameraPosition *camera;
if(self.currentLocationArray.count !=0)
{
lat = [self.currentLocationArray[0] doubleValue];
lon = [self.currentLocationArray[1] doubleValue];
camera = [GMSCameraPosition cameraWithLatitude:lat longitude:lon zoom:12];
}
else
{
lat = [self.storeLatitudeArray[0] doubleValue];
lon = [self.storeLongitudeArray[0] doubleValue];
camera = [GMSCameraPosition cameraWithLatitude:lat longitude:lon zoom:9];
}
GMSMapView *mapView = [GMSMapView mapWithFrame:CGRectZero camera:camera];
for(int i=0; i<self.storeNamesArray.count; i++)
{
GMSMarker *marker = [[GMSMarker alloc] init];
marker.title = self.storeNamesArray[i];
marker.snippet = [NSString stringWithFormat:#"%# $%#", self.priceTypeArray[i], self.storePricesArray[i]];
marker.position = CLLocationCoordinate2DMake([self.storeLatitudeArray[i] doubleValue], [self.storeLongitudeArray[i] doubleValue]);
marker.map = mapView;
}
if(self.currentLocationArray.count !=0)
{
GMSMarker *currentMarker = [[GMSMarker alloc] init];
currentMarker.title = #"Current Location";
currentMarker.snippet = #"You are here";
currentMarker.position = CLLocationCoordinate2DMake(lat, lon);
currentMarker.map = mapView;
currentMarker.icon = [UIImage imageNamed:#"temp_userLocation"];
mapView.selectedMarker = currentMarker;
}
CGRect newFrame = self.view.bounds;
newFrame.size.height = frame.size.height / 2;
mapView.frame = newFrame;
mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
mapView.delegate = self;
[self.view addSubview:mapView];
}
I've published my reworked version of Chris's code on the Google Maps SDK for iOS bug.
The solution involved two changes to Chris's code:
Migrate the Google Map instantiation to viewDidLoad,
Push the network traffic from the Main (UI) thread to a background thread.
I don't know if that's the case here but I had same issue with URLWithString function appears only on iOS 7.0.3, I assume Apple has change the characters this function can use so if it returns nil this is your solution.
What I did is using this function to create the string before using it with URLWithString:
-(NSString *) URLEncodeString:(NSString *) str // New to fix 7.0.3 issue //
{
NSMutableString *tempStr = [NSMutableString stringWithString:str];
[tempStr replaceOccurrencesOfString:#" " withString:#"+" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [tempStr length])];
return [[NSString stringWithFormat:#"%#",tempStr] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
On your case just change the line to this one:
dispatch_async(dispatch_get_main_queue(), ^{ NSData *data =
[NSData dataWithContentsOfURL:[NSURL URLWithString:[self URLEncodeString: [NSString stringWithFormat: #"http://www.someurl.com/mobile-api"]]]];
[self performSelectorOnMainThread:#selector(fetchData:) withObject:data
waitUntilDone:YES]; });
Hope that would help you too.
insert this code in viewDidLoad method
-(void)viewDidLoad
{
[super viewDidLoad];
// iOS7
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
.... your codes
}
I've got Google Map embedded in a View Controller in a Map on an iPhone. I can create my map using:
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:39.93
longitude:-75.17
zoom:12];
mapView_ = [GMSMapView mapWithFrame:CGRectZero camera:camera];
// use GPS to determine location of self
mapView_.myLocationEnabled = YES;
mapView_.settings.myLocationButton = YES;
mapView_.settings.compassButton = YES;
Now, I want to add a kml file (from a URL) that displays a route. I would imagine there is something within GMSMapView to allow this either as a layer or something else, but I'm not having any luck. I've seen the KMS Tutorial but that uses some other kit, MK something. Anyway, is there a way I can load a KML file using the Google Maps for iOS API?
I know this question is more than 1 year old but I couldn't find any solution, so I hope my solution will be useful.
You can load KML into GMSMapView using iOS-KML-Framework. I've ported this code from a project that was using KML-Viewer
Add method for parsing KML from the given URL, make sure you pass correct app bundle to dispatch_queue_create():
- (void)loadKMLAtURL:(NSURL *)url
{
dispatch_queue_t loadKmlQueue = dispatch_queue_create("com.example.app.kmlqueue", NULL);
dispatch_async(loadKmlQueue, ^{
KMLRoot *newKml = [KMLParser parseKMLAtURL:url];
[self performSelectorOnMainThread:#selector(kmlLoaded:) withObject:newKml waitUntilDone:YES];
});
}
Handle the KML parsing result or error:
- (void)kmlLoaded:(id)sender {
self.navigationController.view.userInteractionEnabled = NO;
__kml = sender;
// remove KML format error observer
[[NSNotificationCenter defaultCenter] removeObserver:self name:kKMLInvalidKMLFormatNotification object:nil];
if (__kml) {
__geometries = __kml.geometries;
dispatch_async(dispatch_get_main_queue(), ^{
self.navigationController.view.userInteractionEnabled = YES;
[self reloadMapView];
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
self.navigationController.view.userInteractionEnabled = YES;
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Error", nil)
message:NSLocalizedString(#"Failed to read the KML file", nil)
delegate:nil
cancelButtonTitle:NSLocalizedString(#"OK", nil)
otherButtonTitles:nil];
[alertView show];
});
}
}
Go over the geometry items from KML and add them to the GMSMapView as markers:
- (void)reloadMapView
{
NSMutableArray *annotations = [NSMutableArray array];
for (KMLAbstractGeometry *geometry in __geometries) {
MKShape *mkShape = [geometry mapkitShape];
if (mkShape) {
if ([mkShape isKindOfClass:[MKPointAnnotation class]]) {
MKPointAnnotation *annotation = (MKPointAnnotation*)mkShape;
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = annotation.coordinate;
marker.appearAnimation = kGMSMarkerAnimationPop;
marker.icon = [UIImage imageNamed:#"marker"];
marker.title = annotation.title;
marker.userData = [NSString stringWithFormat:#"%#", geometry.placemark.descriptionValue];
marker.map = self.mapView;
[annotations addObject:annotation];
}
}
}
// set bounds in next run loop.
dispatch_async(dispatch_get_main_queue(), ^{
GMSCoordinateBounds *bounds = [[GMSCoordinateBounds alloc] init];
for (id <MKAnnotation> annotation in annotations)
{
bounds = [bounds includingCoordinate:annotation.coordinate];
}
GMSCameraUpdate *update = [GMSCameraUpdate fitBounds:bounds];
[self.mapView moveCamera:update];
[self.mapView animateToViewingAngle:50];
});
}
At the end of the last method we're updating the camera view to fit all the markers that were added to the map. You can remove this part if it's not needed.
KML is not yet supported in the SDK. Please file a feature request in the issue tracker.
This is how I solved similar problem using mentioned iOS-KML-Framework.
#import <GoogleMaps/GoogleMaps.h>
#import "KML.h"
#property (weak, nonatomic) IBOutlet GMSMapView *mapView;
- (void)loadZonesFromURL:(NSURL *)url {
KMLRoot* kml = [KMLParser parseKMLAtURL: url];
for (KMLPlacemark *placemark in kml.placemarks) {
GMSMutablePath *rect = [GMSMutablePath path];
if ([placemark.geometry isKindOfClass:[KMLPolygon class]]) {
KMLLinearRing *ring = [(KMLPolygon *)placemark.geometry outerBoundaryIs];
for (KMLCoordinate *coordinate in ring.coordinates) {
[rect addCoordinate:CLLocationCoordinate2DMake(coordinate.latitude, coordinate.longitude)];
}
GMSPolygon *polygon = [GMSPolygon polygonWithPath:rect];
polygon.fillColor = [UIColor colorWithRed:67.0/255.0 green:172.0/255.0 blue:52.0/255.0 alpha:0.3];
polygon.map = self.mapView;
}
}
}