Using CLLocationManager on iOS Simulator to find latitude and longitude [duplicate] - objective-c

This question already has answers here:
Location Services not working in iOS 8
(26 answers)
Closed 8 years ago.
I am trying to create an application that opens with a map using MKMapView, and then by creating a delegate to CLLocationManger find the current location of the user.
I have posted my code below. The problem that I am having right now is that that although the map does appear when opening the this the simulator it does not give a position or a new heading from the NSLog that should be passing the latitude and longitude.
I am new to Objective - C and App Development, does anyone see if I am missing some of the protocol for CLLocationManger? Thanks for all your help.
Sorry the code is a little sloppy, pasted it in quickly.
#import "ViewController.h"
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController () <CLLocationManagerDelegate>
#property (nonatomic,strong)CLLocationManager * myLocationManger;
#property (nonatomic,strong) IBOutlet MKMapView *myMapView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"insdie view did load");
// Setting the map to be big as the view
self.myMapView =[[MKMapView alloc]init];
//Initial Property to Map
self.myMapView =[[MKMapView alloc] init];
//Set type to Standard
self.myMapView.mapType = MKMapTypeStandard;
//Set Mask for AutoReszing
self.myMapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
//Add the View!
[self.view addSubview:self.myMapView];
///*Now lets Use my CLLocation Manager to Locate the iPhone's Posistion*////
//Chekcs if Location Services are Enabled
if ([CLLocationManager locationServicesEnabled]) {
self.myLocationManger = [[CLLocationManager alloc] init];
self.myLocationManger.delegate = self;
[self.myLocationManger startUpdatingLocation];
}
else{
//Location Services are available we will need software to ask to turn this On
//The user is SOL if they refuse to turn on Location Services
NSLog(#"Location Services not enabled");
}
}
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
//This method will show us that we recieved the new location
NSLog(#"Latitude = %f",newLocation.coordinate.latitude );
NSLog(#"Longitude =%f",newLocation.coordinate.longitude);
}
-(void)locationManager:(CLLocationManager *)manager
didFinishDeferredUpdatesWithError:(NSError *)error{
NSLog(#"Error with Updating");
}
-(void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
//Failed to recieve user's location
NSLog(#"failed to recived user's locatio");
}

I found that in the new iOS 8, you need two keys added to the Plist. This article explains the process beautifuly.
http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/

Related

didUpdateLocations is not called in ios 9.3.2

didUpdateLocations is never called, instead didFailWithError is called with denied code kCLErrorDenied.
Here are the things that i did:
#import "ViewController.h"
#import CoreLocation;
#interface ViewController () <CLLocationManagerDelegate>
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(nonnull NSArray<CLLocation *> *)locations
{
NSLog(#"update");
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(nonnull NSError *)error
{
NSLog(#"error");
}
#end
Inserted NSLocationWhenInUseUsageDescription and NSLocationAlwaysUsageDescription to the info.plist of the app. Enabled Background Modes in Capabilities with Location updates selected. Get help from the very famous blog post. I receive Location Access Request popup and allow the app to access location.
But i couldnt managed to get location updates. It works in IPAD with IOS 8 but not work at ipad with IOS version 9.3.2. How can i make location updates work in IOS 9.3.2?
trying following thing may resolve your issue:
go to settings and reset your location services
reset your network settings
restarting the simulator
also, if you have Scheme/Edit Scheme/Options/Allow Location Simulation checked but don't have a default location set.
Add NSLocationAlwaysUsageDescription to your plist as type string if using Always authorization. Also, do the same for NSLocationWhenInUseUsageDescription same way if using WhenInUse authorization.
For detail check answers here:
didFailWithError: Error Domain=kCLErrorDomain Code=0 "The operation couldn’t be completed. (kCLErrorDomain error 0.)"
and IOS 9 Error Domain=kCLErrorDomain Code=0 "(null)"

CLLocationManager works with ARC?

All I'm trying to do is get the current position of the User, and show on the map of my app, so I am using CLLocationManager class, as anybody can see below:
ViewController.h
import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface MeuPrimeiroViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>{
IBOutlet MKMapView *mapView;
}
#property(nonatomic, retain) CLLocationManager *locationManager;
#end
ViewController.m
-(void)viewDidAppear:(BOOL)animated{
//Lendo as coordenadas com o core location
if ([CLLocationManager locationServicesEnabled]) {
NSLog(#"CLLocationManager locationServicesEnabled == ON");
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
}else{
NSLog(#"CLLocationManager locationServicesEnabled == OFF");
}
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation{
CLLocationDistance altitude = newLocation.altitude;
CLLocationDegrees latitude = newLocation.coordinate.latitude;
CLLocationDegrees longitude = newLocation.coordinate.longitude;
NSLog(#"Altitude, Latitude, Longitude: %f, %f, %f",altitude,latitude,longitude);
MKCoordinateRegion coordenada = {{0.0,0.0}, {0.0,0.0}};
coordenada.center.latitude = latitude;
coordenada.center.longitude = longitude;
[mapView setRegion:coordenada animated:YES];
//Calculando distancias
CLLocationDistance distancia = [newLocation distanceFromLocation:oldLocation];
NSLog(#"Distancia em metros : %f",distancia);
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
NSLog(#"Error: %#",[error description]);
}
The problem with this code is that my methods of CLLocationManager class not being called, I did some research on the internet over a possible problem related to the ARC, but none of them worked, any suggestions?
iOS 8 changed 2 things that make this not work as it did before
On iOS 8, you need to call requestWhenInUseAuthorization or requestAlwaysAuthorization before calling startUpdatingLocation
You MUST provide a location usage description corresponding to what type of authorization you are requesting in the Info.plist (either NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription). You should also continue to provide the value for the old pre-iOS 8 key (NSLocationUsageDescription) as a fallback for older versions of iOS.
All I'm trying to do is get the current position of the User, and show on the map of my app
You do not need any of that in order to put the user's location on a map. Just tell the map to track the user's location. In iOS 8 you do need user authorization to do this, and for that you do need a location manager. But these two lines of code are sufficient (this is Swift but I'm sure you can translate):
self.locman.requestWhenInUseAuthorization()
self.map.userTrackingMode = .Follow

Why does UILocalNotification with region not fire?

I have followed the example given in the WWDC 2014 session "What's New in iOS Notifications" to set up a UILocalNotification delivery when a region's boundary is crossed.
However, my notification never fires on device nor simulator running iOS beta 3. The notification works fine when I tested using a fireDate instead of a region (not both at same time-- that's not allowed).
I have set NSLocationWhenInUseUsageDescription in my Info.plist.
Here is my Obj-C code:
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#interface ViewController () <CLLocationManagerDelegate>
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, strong) CLLocation *notifLocation;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// test points at Apple HQ
self.notifLocation = [[CLLocation alloc] initWithLatitude:37.331741 longitude:-122.030333];
[self setupLocationMonitoring];
}
- (void) setupLocationMonitoring
{
if (self.locationManager == nil) {
self.locationManager = [[CLLocationManager alloc] init];
}
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.distanceFilter = 10; // meters
// iOS 8+ request authorization to track the user’s location
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
}
- (void)registerLocationNotification
{
UILocalNotification *locNotification = [[UILocalNotification alloc] init];
locNotification.alertBody = #"Hello!";
// doesn't work
locNotification.regionTriggersOnce = NO;
locNotification.region = [[CLCircularRegion alloc] initWithCenter:self.notifLocation.coordinate radius:50 identifier:#"PlaceName"];
// works:
// locNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:10];
UIApplication *application = [UIApplication sharedApplication];
[application cancelAllLocalNotifications];
[application scheduleLocalNotification:locNotification];
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
// check status to see if we’re authorized
BOOL canUseLocationNotifications = (status == kCLAuthorizationStatusAuthorizedWhenInUse);
if (canUseLocationNotifications) {
[self registerLocationNotification];
}
}
#end
Note: this question is about iOS 8's new Location Notifications, not about region monitoring on older versions of iOS.
Your code works fine for me. Here are the steps on iPhone Simulator:
1) Open Simulator app and choose the following option from the top menu Debug -> Location -> Custom Location and put there the coordinates as you have in code: (37.331741, -122.030333)
2) Run your Xcode project on iPhone Simulator
3) Background the app
4) Open the same top menu item Debug -> Location but change it from Custom Location to Freeway Drive or City Run. Play with City Run/ Freeway Drive and Custom Location
I see the notification when I follow these steps. Looks like it doesn't work in case appropriate coordinate is a starting one but it works when the coordinate changes to appropriate from some others.

Annotation with canShowCallout switch viewController

I have a problem. I search with google apis to places and let me create a annotation pin on the map. The data is stored in a dict. I try THESE position to transfer with a callout including the data to another ViewController.
Here are Parts of my code:
.h file:
#import <MapKit/MapKit.h>
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import "MapPoint.h"
#define kGOOGLE_API_KEY #"MyGoogleAPIsKey"
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#interface FirstViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
CLLocationCoordinate2D currentCentre;
BOOL firstLaunch;
int currenDist;
}
- (IBAction)myButton:(UIBarButtonItem *)sender;
- (IBAction)myPosition:(UIBarButtonItem *)sender;
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
#end
.m file:
#implementation FirstViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//Make this controller the delegate for the map view.
self.mapView.delegate = self;
// Ensure that you can view your own location in the map view.
[self.mapView setShowsUserLocation:YES];
//Instantiate a location object.
locationManager = [[CLLocationManager alloc] init];
//Make this controller the delegate for the location manager.
[locationManager setDelegate:self];
//Set some parameters for the location object.
[locationManager setDistanceFilter:kCLDistanceFilterNone];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
firstLaunch=YES;
[_mapView setCenterCoordinate:_mapView.userLocation.coordinate];
}
-(void)plotPositions:(NSArray *)data {
// 1 - Remove any existing custom annotations but not the user location blue dot.
for (id<MKAnnotation> annotation in _mapView.annotations)
{
if ([annotation isKindOfClass:[MapPoint class]])
{
[_mapView removeAnnotation:annotation];
}
}
// 2 - Loop through the array of places returned from the Google API.
for (int i=0; i<[data count]; i++)
{
//Retrieve the NSDictionary object in each index of the array.
NSDictionary* place = [data objectAtIndex:i];
// 3 - There is a specific NSDictionary object that gives us the location info.
NSDictionary *geo = [place objectForKey:#"geometry"];
// Get the lat and long for the location.
NSDictionary *loc = [geo objectForKey:#"location"];
// 4 - Get your name and address info for adding to a pin.
NSString *name = [place objectForKey:#"name"];
NSString *vicinity = [place objectForKey:#"vicinity"];
// 4.5 - Get id for detailed view.
NSString *myId = [place objectForKey:#"id"];
// Create a special variable to hold this coordinate info.
CLLocationCoordinate2D placeCoord;
// Set the lat and long.
placeCoord.latitude=[[loc objectForKey:#"lat"] doubleValue];
placeCoord.longitude=[[loc objectForKey:#"lng"] doubleValue];
// 5 - Create a new annotation.
MapPoint *placeObject = [[MapPoint alloc] initWithName:name address:vicinity coordinate:placeCoord];
[_mapView addAnnotation:placeObject];
NSLog(#"%#", myId);
}
}
-(void)button:(id)sender
{
//here is my main problem ...
}
if i done a misstake or something else tell me that please.
I am grateful for any answer!
okay forget to say I am really new to Obj-C so every tip is usefull for me!
Regards Curtis
As #Anna Karenina said, you can implement the accessory view delegate BUT you must remember to put a UIControl or this method will not be called. Otherwise that view needs to handle its own touch events.
from the documentation:
If the view you specify is also a descendant of the UIControl class,
you can use the map view’s delegate to receive notifications when your
control is tapped. If it does not descend from UIControl, your view is
responsible for handling any touch events within its bounds.
reference

Xcode Interface Builder Not showing App Delegate Object

I am teaching myself Objective-C and iOS programming with "IOS Programming: The Big Nerd Ranch guide (2nd Edition) and I have run into an issue where the tutorial wants me to create connections to an App Delegate object, but this object does not appear in the Objects list in Interface builder for me. I am pretty sure its either a typo or perhaps a version different as the book is slightly behind my version of Xcode (4.2). I have included the code. I am fairly certain that the MOCAppDelegate object is what should be showing up in IB, but I am not yet familiar enough to know what code changes I need to make that happen. Specific question: How do I adjust the code below so that I get an object in the Objects list in IB so that I can perform the connections as instructed in the tutorial graphic?
Note: I researched and found this: Having trouble hooking up instance variables to AppDelegate but this solution did not work for me (or I did not implement it correctly)
Header File
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface MOCAppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
IBOutlet MKMapView *worldView;
IBOutlet UIActivityIndicatorView *activityIndicator;
IBOutlet UITextField *locationTitleField;
}
#property (strong, nonatomic) IBOutlet UIWindow *window;
#end
Implementation File
#import "MOCAppDelegate.h"
#implementation MOCAppDelegate
#synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Create location manager object
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
//We want all results from the location manager
[locationManager setDistanceFilter:kCLDistanceFilterNone];
//And we want it to be as accurate as possible
//regardless of how much time/power it takes
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
//Tell our location manager to start looking for it location immediately
[locationManager startUpdatingLocation];
//We also want to know our heading
if (locationManager.headingAvailable == true) {
[locationManager startUpdatingHeading];
}
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor darkGrayColor];
[self.window makeKeyAndVisible];
return YES;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog(#"%#", newLocation);
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateHeading:(CLHeading *)newHeading
{
NSLog(#"%#", newHeading);
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
NSLog(#"Could not find location: %#", error);
}
- (void)dealloc
{
if( [locationManager delegate] == self)
[locationManager setDelegate:nil];
}
- (void)applicationWillResignActive:(UIApplication *)application
{
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
/*
Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
*/
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application
{
/*
Called when the application is about to terminate.
Save data if appropriate.
See also applicationDidEnterBackground:.
*/
}
#end
Drag an instance of NSObject into your .xib and drop it in the Objects section just as in the instructions you've got. Then select it and change its type in the identity inspector (on the right side, where it says "Custom Class") to "MOCAppDelegate" (or whatever class you like).
You should drag an "NSObject" from the Object Library onto your storyboard on the black bar underneath the view controller you want to connect. Then, click on the NSObject and in the identity inspector change the class to AppDelegate. Then you can create the connection to the AppDelegate.
MOCAppDelegate = AppDelegate
The code was generated for you when you named the project. The delegate of the UIApplication object is usually named slightly different depending on the name of the project.
(There's no doubt that any book in print was using an older Xcode.)
Select Files Owner and the Identity Inspector (command-alt-2) to confirm the file's owner is a place holder for the app delegate.