I am implementing a Geolocation code, which means the I want to take an address as a string and then return a location in the form of a CLCoordinate. I get this strange error code that no one else is seeming to have seen.
kCLErrorDomain error 8
I don't have a map in this because I just want to be able to get a coordinate from an address string. Then use this coordinate later for another part of the program. I feel like I am missing something. Thanks for all your help!
#interface ViewController () <CLLocationManagerDelegate, UISearchBarDelegate>
#property (strong, nonatomic) IBOutlet UISearchBar *BarSearch;
#property (strong,nonatomic) CLGeocoder *Geocoder;
#property (strong,nonatomic) CLLocationManager *locationManager;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc]init];
self.locationManager.delegate = self;
//Check to see if they have Authorization to use to use location servieces
if ([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)])
{
[self.locationManager requestAlwaysAuthorization];
}
[self.locationManager startUpdatingLocation];
//Setup UISearch Bar
self.BarSearch.delegate=self;
}
The program does enter this method, but only to return this error:
kCLErrorDomain error 8
-(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
self.Geocoder = [[CLGeocoder alloc]init];
[self.Geocoder geocodeAddressString:#"Springfield, MA" completionHandler:^(NSArray* placemarks, NSError* error){
if (!error) {
for (CLPlacemark* aPlacemark in placemarks)
{
NSLog(#"place--%#", [aPlacemark locality]);
NSLog(#"lat--%f\nlong-- %f",aPlacemark.location.coordinate.latitude,aPlacemark.location.coordinate.longitude);
}
}
else{
NSLog(#"error--%#",[error localizedDescription]);
}
}];
}
Silly mistake, but just by restarting the iOS Simulator the problem was resolved.
Have you added to your info plist this key : NSLocationAlwaysUsageDescription
Related
This is my first post every here. Woohoo.
Here is my story ... I spent about a week trying tutorials about geofencing in IOS. The problem is that i have to do it in Objective-C for now.
I am trying to get a small app to run this geofencing but i keep having problems with the actual trigger events.
I am testing it on my actual phone (iPhone 7Plus) and i can't get to make some events show on the screen whether i'm inside the region or out.
i will paste code from the .h and .m files. these are the only ones that i have implemented so far.
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController <CLLocationManagerDelegate>
#property (weak, nonatomic) IBOutlet UILabel *myLat;
#property (weak, nonatomic) IBOutlet UILabel *myLon;
#property (weak, nonatomic) IBOutlet UILabel *destLat;
#property (weak, nonatomic) IBOutlet UILabel *destLon;
#property (weak, nonatomic) IBOutlet UILabel *diff;
#property (weak, nonatomic) IBOutlet UILabel *answer;
#property BOOL alwaysOn;
#property BOOL isCLickOn;
#property (retain, nonatomic) CLLocationManager *locationManager;
#end
... and this what i have in my .m file:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void) viewDidAppear:(BOOL)animated{
// [self showAlertMessage:#"Test" message:#"Maybe works"];
// [self showAlertMessage:#"Test" message:#"Maybe works"];
[self setupTheAuthorizations];
if(!_isCLickOn){
[self startTheRegionMonitoring];
}
// _answer.text = #"Merge";
}
- (void) setupTheAuthorizations {
_locationManager = [[CLLocationManager alloc] init];
[_locationManager requestAlwaysAuthorization];
_locationManager.delegate = self;
[_locationManager startUpdatingLocation];
//check the type of authorization
CLAuthorizationStatus authStatus = [CLLocationManager authorizationStatus];
switch (authStatus) {
case kCLAuthorizationStatusAuthorizedAlways:
// should do somethinglike getting the things started and stuff like that ...
_alwaysOn = YES;
break;
case kCLAuthorizationStatusNotDetermined:
[_locationManager requestAlwaysAuthorization];
default:
break;
}
}
- (void) startTheRegionMonitoring {
if (_alwaysOn && [CLLocationManager isMonitoringAvailableForClass:[CLRegion class]]){
CLLocationDegrees latitude = 37.972004;
CLLocationDegrees longitude = -121.293740;
CLLocationDistance radius = 200;
CLLocationCoordinate2D center = CLLocationCoordinate2DMake(latitude, longitude);
CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:center radius:radius identifier:#"CH"];
region.notifyOnEntry = YES;
region.notifyOnExit = YES;
_destLat.text = [NSString stringWithFormat:#"%f", latitude];
_destLon.text = [NSString stringWithFormat:#"%f", longitude];
_myLat.text = [NSString stringWithFormat:#"%f", _locationManager.location.coordinate.latitude];
_myLon.text = [NSString stringWithFormat:#"%f", _locationManager.location.coordinate.longitude];
[_locationManager startMonitoringForRegion:region];
}
_isCLickOn = YES;
}
- (void)locationManager:(CLLocationManager *)manager
didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
}
- (void)locationManager:(CLLocationManager *)manager
didEnterRegion:(CLRegion *)region{
NSLog(#"entered region");
if ([region.identifier isEqualToString:#"CH"]){
_answer.text = #"IN";
CLLocation *me = [[CLLocation alloc] initWithLatitude:_locationManager.location.coordinate.latitude
longitude:_locationManager.location.coordinate.longitude];
CLLocation *dest = [[CLLocation alloc] initWithLatitude:37.972004
longitude:-121.293740];
int dist = [me distanceFromLocation:dest];
_diff.text = [NSString stringWithFormat:#"%i", dist];
}
}
- (void)locationManager:(CLLocationManager *)manager
didExitRegion:(CLRegion *)region{
NSLog(#"entered region");
if ([region.identifier isEqualToString:#"CH"]) {
_answer.text = #"OUT";
CLLocation *me = [[CLLocation alloc] initWithLatitude:_locationManager.location.coordinate.latitude
longitude:_locationManager.location.coordinate.longitude];
CLLocation *dest = [[CLLocation alloc] initWithLatitude:37.972004
longitude:-121.293740];
int dist = [me distanceFromLocation:dest];
_diff.text = [NSString stringWithFormat:#"%i", dist];
}
}
- (void)locationManager:(CLLocationManager *)manager
didStartMonitoringForRegion:(CLRegion *)region __OSX_AVAILABLE_STARTING(__MAC_10_8,__IPHONE_5_0) __TVOS_PROHIBITED __WATCHOS_PROHIBITED{
NSLog(#"Monitoring started");
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
NSLog(#"error");
}
- (void) showAlertMessage:(NSString *)title message:(NSString *)message {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancel = [UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
[self dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:cancel];
[self presentViewController:alert animated:YES completion:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
What happens is that i don't get any events showing on my phone even when the app is open. so I have a view controller on the storyboard that is supposed to show my location and destination location and to show the distance between the two objects. But it doesn't show it even if i walk 400 meters and then i walk back to the center.
I know that Swift is what I should use, and I will switch to Swift but for right now I am really wanting to understand the process that goes in this geofencing thing.
Any help will be appreciated. I am also pretty new at programming so I still have things that I am trying to learn and understand about Objective-C in particular.
Thank you.
I am developing an application in Xcode 7.3 for iphone 9.3.3 in Objective-C. I followed the suggestions found on this site -- http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/ to get the iphone's location. I am testing what I have so far using an iphone 9.3.3 over lightning cable.
I have "NSLocationWhenInUseUsageDescription" added to the plist with a value of "Request Location".
I am confused as to why this isn't working. I am not getting any strings with the location over NSLog.
Any help is highly appreciated.
ViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface ViewController : UIViewController<CLLocationManagerDelegate>
#property (strong, nonatomic) CLLocationManager *locationManager;
#property (weak, nonatomic) CLLocationManager *locations;
//
//#property (weak, nonatomic) IBOutlet UILabel *longitudelabel;
//#property (weak, nonatomic) IBOutlet UILabel *latitudelabel;
#end
ViewController.m
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "ViewController.h"
#interface ViewController ()
{
NSUserDefaults *defaults;
}
#end
#implementation PollenViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// ** Don't forget to add NSLocationWhenInUseUsageDescription in MyApp-Info.plist and give it a string
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
// 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)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
// Location Manager Delegate Methods
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"%#", [locations lastObject]);
}
#end
With iOS 8, requesting permission and beginning to use location services are now separate actions. Since
requestWhenInUseAuthorization
and
requestAlwaysAuthorization
methods runs asynchronously, the app can't start the location services immediately. Instead, you need to implement
locationManager:didChangeAuthorizationStatus
delegate method as follows, which fires any time the authorization status changes based on user input.
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
if (status == kCLAuthorizationStatusAuthorizedAlways
|| status == kCLAuthorizationStatusAuthorizedWhenInUse) {
[manager startUpdatingLocation];
}
}
If the user has previously given permission to use location services, the delegate method will also be called after the location manager is initialized and has its delegate set with the appropriate authorization status as follows
CLLocationManager *manager = [CLLocationManager new]
Manager.delegate = self;
if [CLLocationManager locationServicesEnabled] {
[manager startUpdatingLocation];
}
I have been able to get the location and display it in the app with the following code for ViewController.m. #DuncanC's comment helped alot. This also includes the reverse geocoding.
-Used NSLocationWhenInUseUsageDescription in the Info.plists with String "Need Location".
-Made sure Settings->Privacy->Location Services->AppName was set to "While Using" not "Never".
Hope this is helpful to anyone who's stuck.
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "CoreLocation/CoreLocation.h"
#interface ViewController ()
{
NSUserDefaults *defaults;
NSString *locationfound;
}
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
#implementation PollenViewController {
CLGeocoder *geocoder;
CLPlacemark *placemark;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//implement location finder
self.locationManager=[[CLLocationManager alloc] init];
self.locationManager.delegate=self;
self.locationManager.desiredAccuracy=kCLLocationAccuracyBest;
//initialize geocoder for later
geocoder = [[CLGeocoder alloc] init];
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
//CURRENTLY WORKING LOCATION MANAGER
//roughly based on ---/*https://gist.github.com/paulw11/84b18044942e2ceea52a8*/
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:
(CLAuthorizationStatus)status {
defaults = [NSUserDefaults standardUserDefaults];
NSLog(#"Callback");
NSLog(#"status %i",status);
if (status == kCLAuthorizationStatusAuthorizedAlways || status == kCLAuthorizationStatusAuthorizedWhenInUse) {
NSLog(#"Authorized");
[self.locationManager startUpdatingLocation];
} else if (status == kCLAuthorizationStatusDenied || status == kCLAuthorizationStatusRestricted) {
NSLog(#"Denied");
locationfound=[NSString stringWithFormat:#"No Location Found"];;
self.LocationLabel.text=locationfound;
}else{
[self.locationManager requestWhenInUseAuthorization];
[self.locationManager requestAlwaysAuthorization];
}
}
// Location Manager Delegate Methods
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *newLocation = [locations lastObject];
NSLog(#"Location new %#",newLocation) ;
// Reverse Geocoding
NSLog(#"Resolving the Address");
[geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *placemarks, NSError *error) {
defaults = [NSUserDefaults standardUserDefaults];
// NSLog(#"Found placemarks: %#, error: %#", placemarks, error);
if (error == nil && [placemarks count] > 0) {
placemark = [placemarks lastObject];
locationfound= [NSString stringWithFormat:#"%#, %#",
placemark.locality,
placemark.administrativeArea];
NSLog(#"%#",locationfound);
self.LocationLabel.text=locationfound;
} else {
NSLog(#"%#", error.debugDescription);
locationfound=[NSString stringWithFormat:#"No Location Found"];;
self.LocationLabel.text=locationfound;
}
} ];
}
#end
You could try
- (void)locationManager:(CLLocationManager*) manager didFailWithError:(NSError*)error
To see if the update is failing and why
I am trying to get the user's current location using the Core Location Framework in Xcode 6.3.1, I did following things:
Added Core Location Framework under Target-> General-> Linked Frameworks & Libraries
My ViewController.h file is as shown below,
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController<CLLocationManagerDelegate>
#property (weak, nonatomic) IBOutlet UILabel *lblLatitude;
#property (weak, nonatomic) IBOutlet UILabel *lblLongitude;
#property (weak, nonatomic) IBOutlet UILabel *lblAddress;
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
My ViewController.m file is as shown below,
- (void)viewDidLoad
{
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if(IS_OS_8_OR_LATER){
NSUInteger code = [CLLocationManager authorizationStatus];
if (code == kCLAuthorizationStatusNotDetermined && ([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)] || [self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)])) {
if([[NSBundle mainBundle] objectForInfoDictionaryKey:#"NSLocationAlwaysUsageDescription"]){
[self.locationManager requestAlwaysAuthorization];
} else if([[NSBundle mainBundle] objectForInfoDictionaryKey:#"NSLocationWhenInUseUsageDescription"]) {
[self.locationManager requestWhenInUseAuthorization];
} else {
NSLog(#"Info.plist does not contain NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription");
}
}
}
[self.locationManager startUpdatingLocation];
}
#pragma mark - CLLocationManagerDelegate
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"didFailWithError: %#", error);
UIAlertView *errorAlert = [[UIAlertView alloc]
initWithTitle:#"Error" message:#"Failed to Get Your Location" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[errorAlert show];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"didUpdateToLocation: %#", newLocation);
CLLocation *currentLocation = newLocation;
if (currentLocation != nil) {
lblLatitude.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
lblLongitude.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
}
}
#end
I had also added the following keys in my info.plist file
NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
Checked everything given here, here, here, here, and a lot more list
So, is anyone having a solution for this issue, kindly help. Have lost my mind searching for this for the whole day.
Yeah! Got the solution, Here is my whole code & things added to make it working. Special thanks to #MBarton for his great help. Also Thanks to # Vinh Nguyen for investing his precious time in solving my issue.
Added Core Location Framework under Target-> General-> Linked Frameworks & Libraries
Added in .plist file
NSLocationAlwaysUsageDescription
See Screenshot:
In my ViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <MapKit/MKAnnotation.h>
// #define IS_OS_8_OR_LATER ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
#interface ViewController : UIViewController <MKMapViewDelegate, CLLocationManagerDelegate>
{
__weak IBOutlet UINavigationItem *navigationItem;
}
#property (weak, nonatomic) IBOutlet MKMapView *mapView;
#property(nonatomic, retain) CLLocationManager *locationManager;
#end
Then in ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize mapView;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self setUpMap];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)setUpMap
{
mapView.delegate = self;
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
#ifdef __IPHONE_8_0
// if(IS_OS_8_OR_LATER) {
if ([self.locationManager respondsToSelector:#selector(requestAlwaysAuthorization)]) {
// Use one or the other, not both. Depending on what you put in info.plist
[self.locationManager requestAlwaysAuthorization];
}
#endif
[self.locationManager startUpdatingLocation];
mapView.showsUserLocation = YES;
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
}
-(void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
NSLog(#"%#", [self deviceLocation]);
//View Area
MKCoordinateRegion region = { { 0.0, 0.0 }, { 0.0, 0.0 } };
region.center.latitude = self.locationManager.location.coordinate.latitude;
region.center.longitude = self.locationManager.location.coordinate.longitude;
region.span.longitudeDelta = 0.005f;
region.span.longitudeDelta = 0.005f;
[mapView setRegion:region animated:YES];
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
}
- (NSString *)deviceLocation {
return [NSString stringWithFormat:#"latitude: %f longitude: %f", self.locationManager.location.coordinate.latitude, self.locationManager.location.coordinate.longitude];
}
Ufff...! Got the solution after fighting with many codes since last 5 days...
I've followed online tutorials from AppCoda and Devfright to create an iBeacon detection app. I'm using an iBeacon from estimote, an iPad 3 with iOS 8. The app simply does not detect my iBeacon whereas its being detected by other iBeacon apps. I can't understand what I'm missing or doing wrong in my code.
Here's my .h file:
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController<CLLocationManagerDelegate>
#property (nonatomic, strong) CLBeaconRegion *beaconRegion;
#property (nonatomic, strong) CLLocationManager *locManager;
#property (nonatomic, strong) IBOutlet UILabel *label1;
#property (nonatomic, strong) IBOutlet UILabel *label2;
#end
Here's my .m file:
#import "ViewController.h"
#import <CoreLocation/CoreLocation.h>
#interface ViewController () <CLLocationManagerDelegate>
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.locManager = [[CLLocationManager alloc] init];
self.locManager.delegate = self;
//default uuid for estimote beacons
NSUUID *uuid = [[NSUUID alloc] initWithUUIDString:#"B9407F30-F5F8-466E-AFF9-25556B57FE6D"];
self.beaconRegion = [[CLBeaconRegion alloc]initWithProximityUUID:uuid identifier:#"com.rk.testregion"];
[self.locManager startMonitoringForRegion:self.beaconRegion];
[self locationManager:self.locManager didStartMonitoringForRegion:self.beaconRegion];
// Check if beacon monitoring is available for this device
if (![CLLocationManager isMonitoringAvailableForClass:[CLBeaconRegion class]]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Monitoring not available" message:nil delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles: nil]; [alert show]; return;
}
}
-(void)locationManager:(CLLocationManager*)manager didRangeBeacons:(NSArray*)beacons inRegion:(CLBeaconRegion*)region
{
// Beacon found!
self.label1.text = #"Welcome to";
self.label2.text = #"Location 1";
CLBeacon *foundBeacon = [beacons firstObject];
// retrieve the beacon data from its properties
NSString *uuid = foundBeacon.proximityUUID.UUIDString;
NSString *major = [NSString stringWithFormat:#"%#", foundBeacon.major];
NSString *minor = [NSString stringWithFormat:#"%#", foundBeacon.minor];
NSLog(#"UUID: %#", uuid);
NSLog(#"major: %#", major);
NSLog(#"minor: %#", minor);
}
- (void)viewDidDisappear:(BOOL)animated
{
[self.locManager stopRangingBeaconsInRegion:self.beaconRegion];
[super viewDidDisappear:animated];
}
- (void)locationManager:(CLLocationManager*)manager didEnterRegion:(CLRegion*)region
{
[self.locManager startRangingBeaconsInRegion:self.beaconRegion];
}
-(void)locationManager:(CLLocationManager*)manager didExitRegion:(CLRegion*)region
{
[self.locManager stopRangingBeaconsInRegion:self.beaconRegion];
self.label1.text = #"Searching again...";
}
- (void)locationManager:(CLLocationManager *)manager didStartMonitoringForRegion:(CLRegion *)region {
[self.locManager startRangingBeaconsInRegion:self.beaconRegion];
}
#end
The delegate method didRangeBeacons simply does not get called. Could someone please let me know how to fix this.
Check out the answer below, which describes some extra hoops you now need to jump through to get this working:
Location Services not working in iOS 8
Full disclosure: I have not tried this myself.
The goal I want to achieve:
I want to display the user address in a view. The view is taken care of by a view controller . This VC is using the GeoAPI to get access to the user location. The GeoAPI is wrapped around the LocationManager-Class which in turn is taking care of all the locationmanager stuff. In this location Manager class I would like to reversegeocode as mentioned above.
The geoAPI has some convenience methods that can be used to get the information I want.
GeoAPI:
#import <Foundation/Foundation.h>
#interface MFGeoAPI : NSObject
#property (nonatomic, strong) NSDictionary *userLocationInfoDict;
+ (MFGeoAPI *)sharedInstance;
- (CLLocation *)getCurrentUserLocation;
#end
#interface MFGeoAPI () {
LocationManager *locationManager;
MotionManager *motionManager;
}
#end
#implementation MFGeoAPI
+(MFGeoAPI *)sharedInstance {
static MFGeoAPI *_sharedInstance = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedInstance = [[MFGeoAPI alloc] init];
});
return _sharedInstance;
}
- (id)init {
if (self = [super init]) {
locationManager = [[LocationManager alloc] initLocationManager];
motionManager = [[MotionManager alloc] initMotionManager];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(getUserLocationInformation:) name:#"UserLocationInfo" object:nil];
return self;
}
- (CLLocation *)getCurrentUserLocation {
return [locationManager getCurrentUserLocation];
}
- (void)getUserLocationInformation:(NSNotification *)notification {
NSLog(#"OK");
self.userLocationInfoDict = [[NSDictionary alloc] initWithDictionary:notification.userInfo];
}
#end
Now.. due to the fact of the async character of the reverse geocode function I won't be sure when the dictionary with the user address will be available.
The Location Manager class contains the following:
Location Manager:
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface LocationManager : NSObject <CLLocationManagerDelegate>
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, strong) CLLocation *userLocation;
#property (nonatomic, strong) NSDictionary *userLocDict;
- (id)initLocationManager;
- (CLLocation *)getCurrentUserLocation;
#end
#import "LocationManager.h"
#implementation LocationManager
- (id)initLocationManager {
if (self = [super init]) {
if (self.locationManager == nil) {
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
if (![self.locationManager locationServicesEnabled]) {
UIAlertView *servicesDisabledAlert = [[UIAlertView alloc] initWithTitle:#"Location Services Disabled" message:#"You currently have all location services for this device disabled. If you proceed, you will be asked to confirm whether location services should be reenabled." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[servicesDisabledAlert show];
}
}
[self startUpdatingLocation];
[self startFetchingCurrentUserLocationInformation];
}
return self;
}
- (void)startUpdatingLocation {
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
self.locationManager.headingFilter = kCLHeadingFilterNone;
[self.locationManager startUpdatingHeading];
[self.locationManager startUpdatingLocation];
self.userLocation = self.locationManager.location;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(#"FAILED");
}
- (CLLocation *)getCurrentUserLocation {
return self.userLocation;
}
- (void)startFetchingCurrentUserLocationInformation {
[self delayedReverseGeocodeLocation];
}
- (void)delayedReverseGeocodeLocation {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self reverseGeocodeLocation];
}
- (void)reverseGeocodeLocation {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder reverseGeocodeLocation:self.userLocation completionHandler:^(NSArray *placemarks, NSError *error) {
NSDictionary *dict = [[placemarks firstObject] addressDictionary];
if (placemarks.count > 0) {
NSDictionary *info = [NSDictionary dictionaryWithObject:dict forKey:#"transferDict"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"UserLocationInfo" object:self userInfo:info];
}
}];
}
In the view Controller I would like to get access to the userLocation Information Dictionary that I am passing through the API
View Controller
- (id)init {
if (self = [super init]) {
self.userLocation = [[MFGeoAPI sharedInstance] getCurrentUserLocation];
NSLog(#"%#", [[MFGeoAPI sharedInstance].userLocationInfoDict description]);
}
return self;
}
But the userlocationInfoDict is empty. I guess this is due to the fact that my function-call "startFetchingCurrentUserLocationInformation" is returning before the async block returns the values I need. Then I thought by taking care of this through NSNotificationCenter I will be informed when the data is available. But now I am stuck:
What do I have to do to get access to the userLocationInformation passed by the GeoAPI to do it in time when the data has arrived?
Any help appreciated!
Thank you
Sebastian