I am trying to transfer a users location from a screen where I allow the user to take a picture to another view where I have a map. The purpose of this is to tag the image location on the map and have that be related with the image. The current code I have for launching the ability to take an image is as follows:
- (IBAction)takePhoto:(UIButton *)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:picker animated:YES completion: NULL];
}
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// Pin location as annotation on map
NSString *dateString = [NSDateFormatter localizedStringFromDate:[NSDate date]
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterFullStyle];
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
MKUserLocation *userLocation = [[MKUserLocation alloc] init];
MKMapView *mapView = [[MKMapView alloc] init];
point.coordinate = userLocation.coordinate;
point.title = #"Picture Entry";
point.subtitle = dateString;
[mapView addAnnotation:point];
// Close camera and go back to home screen
[self dismissModalViewControllerAnimated:YES];
}
I'm new to iOS programming and I'm not sure how to pass the location back to my mapView, and I believe in this code I'm just initializing a new map to save the annotation to, and thats not what I want obviously.
MapViewController.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController <MKMapViewDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
#end
MapViewController.m
#import "MapViewController.h"
#interface MapViewController ()
#end
#implementation MapViewController
#synthesize mapView;
- (void)viewDidLoad
{
// Get user location
mapView.showsUserLocation = YES;
self.mapView.delegate = self;
}
// Update map based on user location and zoom to area
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:
(MKUserLocation *)userLocation
{
mapView.centerCoordinate = userLocation.location.coordinate;
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
#end
This is what I have for now, and I'm at a loss for how to handle this.
I believe in this code I'm just initializing a new map to save the annotation to, and thats not what I want obviously.
You're right -- you're creating a new map and adding the annotation to that object. (Also, you're not creating the map view correctly -- you should use -initWithFrame: because that's a designated initializer for views.)
You should rethink your approach. What you seem to be trying to do is to modify the map view of one view controller (your MapViewController) from a different view controller (assuming that the image picker delegate is some view controller other than MapViewController). A view controller should be in charge of its own views but shouldn't mess with the views of another view controller. Also, adding the annotation that way means that you're effectively storing the location in the map view, and you should avoid using views to store data.
Instead, think about where you should really be saving your data. The M in MVC is for model, i.e. that part of your app that manages the data. As you can see in the acronym, it should be separate from your view(s) and from your controller(s). The model is something that your various view controllers can all use to get the information they need, and having one makes your app simpler because you don't have to worry as much about sending data back and forth between view controllers. The model doesn't have to be anything terribly complicated -- for very simple apps that mainly manage a list of items, even an plain old NSArray or NSSet could serve as a data model. Give each view controller that needs it a reference to the model, or to part of the model.
With that in mind, the right way to fix your app is to have some sort of data model. The image picker delegate should update the map by adding information to the model. The map view controller should be in charge of adding annotations to the map view, and it can do that based on the information in the model.
Related
I created the following method to add pins to my map view. I have tried calling it to get it to add the single pin but it does nothing when I call it from a different view controller?
-(void)addPins:(NSDecimalNumber*) woX ycoord:(NSDecimalNumber*) woY {
CLLocationCoordinate2D coordinate;
coordinate.latitude = 35;
coordinate.longitude = -80;
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
[annotation setCoordinate:coordinate];
[annotation setTitle:#"Title"];
[self.mapView addAnnotation:annotation];
}
I can call it from viewDidLoad of the DetailViewController and it will display the single pin:
[self addPins:woX ycoord:woY];
But when I call it from the MasterViewController nothing displays, but will log the comments so I know that it was run?
DetailViewController *firstController = [[DetailViewController alloc] init];
[firstController addPins:woX ycoord:woY];
I think this happens because the map object doesn't loaded yet in memory when you calling [firstController addPins:woX ycoord:woY]; can you try to call it after delay like this way [firstController performSelectorWithObjects:#[woX, woY] afterDelay:1.0f]
Good luck
Anna was on the right path. I was creating a new instance of the DetailViewController.
I was able to solve it by adding
#property (strong, nonatomic) DetailViewController *detailViewController;
to the MasterViewController.h. And then just calling
[self.detailViewController addPins:woX ycoord:woY desc:cellView];
in MasterViewController.m
i am using google map api for display the location and search bar for search the location but when the GSMMarker display it snippet window hide inside the uisearchbar so any own please help me.
-(void) setupMarkerOnMap:(CLLocation *)loc PlaceName:(NSString *) strCityName
{
[[self getGoogleMap] clear];
[self getNextButton].enabled = YES;
placeMarker = [GMSMarker markerWithPosition:loc.coordinate];
placeMarker.map = [self getGoogleMap];
[placeMarker setTappable:NO];
placeMarker.snippet = strCityName;
placeMarker.icon = [UIImage imageNamed:#"LocationMarker.png"];
GMSCameraUpdate *updateCamera = [GMSCameraUpdate setTarget:placeMarker.position zoom:10.0];
[[self getGoogleMap] animateWithCameraUpdate:updateCamera];
[[self getGoogleMap] setSelectedMarker:placeMarker];
}
these my code snippet for marker add in google map and i attached image which can help you.
anyone can help me.
Thanks
First of all, Make sure that your Google map does not stack together with the search bar. Then you can use delegate to help you move the animate the marker's position inside the Google Map when you tap on any of the marker. Example code:-
Implement the Google Map Delegate
#interface YourViewController ()<GMSMapViewDelegate>
#property (weak, nonatomic) IBOutlet GMSMapView *mapView;
#end
Set the mapView Delegate to the current view controller
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
}
Whenever a marker is tapped, the
-(BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker{
[mapView animateToLocation:marker.position];
return YES;
}
If you have everything setup correctly and the map is big enough, info window should be displayed nicely inside the map.
Currently learning iOS development. I need to set my instance of MKMapView to display with satellite view. I know I can do this through the attribute settings, but I wish to do it through code using [myMapView setMapType:MKMapTypeSatellite], but my question is, where do I put this so that as soon as the mapView loads on the screen, it is already in satellite mode. My instinct is to send this message once my instance of mapview is instantiated, but where does this occur?
Typically this type of code is put into the view controller's viewDidLoad method, which is called once for each instance of a controller.
- (void)viewDidLoad {
[super viewDidLoad];
myMapView = [[MKMapView alloc] initWithFrame:CGRectMake(0,0,200,200)];
myMapView.mapType = MKMapTypeSatellite;
[self.view addSubview:myMapView];
}
I am totally new to iOS development, and am creating a mapping application for a local river. The point of the application is to allow users to map out a route on the river by selecting different points. I am using MapKit to work on this, but have run into some issues. My main issue is how to add a button to an annotation so that once clicked, a detail window will open and the user can learn more about the point as well as add it to the trip. Here's my code, any thoughts will help!
#import "ViewController.h"
#import "CoreLocation/CLLocation.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
// Add an annotation
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = userLocation.coordinate;
point.title = #"Where am I?";
point.subtitle = #"I'm here!!!";
[self.mapView addAnnotation:point];
point.coordinate = CLLocationCoordinate2DMake(33.62258872997,-86.599988937378);
point.title = #"Civitan Park";
point.subtitle = #"Trussville, AL";
[self.mapView addAnnotation:point];
}
#end
Your map view delegate should implement –mapView:viewForAnnotation: and return an annotation view that has one of its accessory view properties set. The normal thing is to set the rightCalloutAccessoryView property to a UIButton whose type is UIButtonTypeDetailDisclosure. You map delegate should also implement -mapView:annotationView:calloutAccessoryControlTapped:, which will be called when the user taps the button in the accessory view. You can then push a detail view controller onto the navigation stack, or whatever else you like.
I would like to find out userlocation coordinate while my app is loading. I have implemented following code but it returns 0.000
mapView.showsUserLocation=YES;
CLLocationCoordinate2D annotationCoordinate;
annotationCoordinate.latitude=mapView.userLocation.location.coordinate.latitude;
NSLog(#"%f",annotationCoordinate.latitude);
I could not able to figure out. Any help?
First of all you should take into account that it takes time to retrieve the user location. Moreover the user can disable the location service for your application or even the location service can be unavailable during the connectivity conditions. So you'd better to rethink your application starting procedures.
When you make up you decision take a look at mapView:didUpdateUserLocation: method of MKMapViewDelegate protocol. After this method fires out the location can be available via the userLocation property of the MKMapView.
UPDATE
In case you want to open map view with the user location already checked, you may consider using CLLocationManager and CLLocationManagerDelegate. This way you can check if the location service is available and open map view after the method locationManager:didUpdateToLocation:fromLocation: fires up.
For the complete info take a look at Getting the User’s Location programing guide
You can not get users location coordinate in view did load what you need to do is using the delegate method below.
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
NSLog(#"coordinates = %f,%f", mapView.userLocation.coordinate.latitude,
mapView.userLocation.coordinate.longitude);
}
Make sure your map object is connected with the delegate
Just tested it should work
1) Add the FrameWork CoreLocation and Mapkit
2) In ViewController.h file
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController<MKMapViewDelegate,CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
}
#property (nonatomic, strong) IBOutlet MKMapView *mapView;
3) In viewController.m file
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate=self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation];
}
now in didUpdateUserLocation
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
// Add an annotation
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = userLocation.coordinate;
point.title = #"Where am I?";
point.subtitle = #"I'm here!!!";
[self.mapView addAnnotation:point];}
4) Now add Mapview in your UI
NOTE: select MapView and goto Attribute Inspector and CKECK Mark the Shows user location Under BEHAVIOUR
I think you should use this:
#import <CoreLocation/CoreLocation.h>
Then in viewDidLoad method:
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
[locationManager startUpdatingLocation];
[mapView setRegion:MKCoordinateRegionMake(locationManager.location.coordinate, MKCoordinateSpanMake(0.2, 0.2))];
mapView.showsUserLocation = YES;
NSLog(#"%f",mapView.region.center.latitude);
Okay, so I just managed to fix it myself too. What no one is telling you is that you need to set a key/value pair in the info.plist.
Depending on what method (requestAlwaysAuthorization or requestWhenInUseAuthorization) you need to add a key under the 'Information Property List' dictionary. For the first method use: NSLocationAlwaysUsageDescription and for the second method use: NSLocationWhenInUseUsageDescription .
The value fields of both keys can be set to whatever string you would like to display to the user.
Both keys at the top are what we are looking for.
Now you should see a dialogue that prompts you for confirmation.
PS: No tutorial on the internet listed this step of the process, but when you read the documentation for each of those methods (requestWhenInUse on CLLocationManager) it does mention that nothing gets displayed without those two keys.