Pass NSString from didUpdateLocations in NSObject to a UIViewController - ios

I created an iOS project and I implemented didUpdateLocations to get my location in a NSObject. I want to get the longitude and the latitude from the delegate to a UIViewController but the result is always null even to test the addObserver I couldn't. In the bottom there is a sample that I did and it shows my location in the label. I implemented didUpdateLocations in the viewcontroller and without a NSObject Class.
This my code in the NSObject:
#import "GpsModel.h"
#implementation GpsModel{
CLLocation *crnLoc;
}
#synthesize locationManager;
#synthesize longitude;
#synthesize latitude;
- (void) initLocation {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager requestWhenInUseAuthorization];
[locationManager requestAlwaysAuthorization];
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
//[self showAlert];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
crnLoc = [locations lastObject];
longitude = [NSString stringWithFormat:#"%.8f",crnLoc.coordinate.longitude];
latitude = [NSString stringWithFormat:#"%.8f",crnLoc.coordinate.longitude];
}
#end
and this is my ViewController :
#import "GpsViewController.h"
#interface GpsViewController ()
#end
#implementation GpsViewController{
CLLocationManager *locationManager;
}
#synthesize gpsView;
#synthesize gpsModel;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
gpsView = [[GpsView alloc] initWithFrame:CGRectMake(0, 0, widthtScreen, heightScreen)];
[self.view addSubview:gpsView];
gpsModel = [GpsModel new];
[gpsModel initLocation];
gpsView.longitudeLabel.text = gpsModel.longitude;
[gpsView.longitudeLabel addObserver:self forKeyPath:#"text" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
gpsView.latitudeLabel.text = gpsModel.latitude;
[gpsView.latitudeLabel addObserver:self forKeyPath:#"text" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if(object == gpsView.longitudeLabel)
{
NSLog(#"long");
}
if(object == gpsView.latitudeLabel)
{
NSLog(#"lat");
}
}
#end
And this my code without the creation of a NSObject Class :
#interface GpsViewController ()
#end
#implementation GpsViewController{
CLLocationManager *locationManager;
CLLocation *crnLoc;
}
#synthesize gpsView;
#synthesize gpsModel;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
gpsView = [[GpsView alloc] initWithFrame:CGRectMake(0, 0, widthtScreen, heightScreen)];
[self.view addSubview:gpsView];
[self initLocation];
}
- (void) initLocation {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager requestWhenInUseAuthorization];
[locationManager requestAlwaysAuthorization];
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
[self showAlert];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
crnLoc = [locations lastObject];
NSLog(#"position long : %#",[NSString stringWithFormat:#"%.8f",crnLoc.coordinate.longitude]);
NSLog(#"position lat : %#",[NSString stringWithFormat:#"%.8f",crnLoc.coordinate.latitude]);
gpsView.longitudeLabel.text = [NSString stringWithFormat:#"%.8f",crnLoc.coordinate.longitude];
[gpsView.longitudeLabel addObserver:self forKeyPath:#"text" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
gpsView.latitudeLabel.text = [NSString stringWithFormat:#"%.8f",crnLoc.coordinate.latitude];
[gpsView.latitudeLabel addObserver:self forKeyPath:#"text" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if(object == gpsView.longitudeLabel)
{
NSLog(#"observe1");
}
if(object == gpsView.latitudeLabel)
{
NSLog(#"observe2");
}
}
and this is my view that contains 2 labels
#implementation GpsView{
CGFloat _originY;
}
#synthesize longitudeLabel;
#synthesize latitudeLabel;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_originY = 50;
[self _initView];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
[self _initView];
}
return self;
}
- (void)_initComponents {
longitudeLabel = [[UILabel alloc] init];
latitudeLabel = [[UILabel alloc] init];
}
- (void)_initView {
[self _initComponents];
[self _createComponentView];
}
-(void) _createComponentView {
_originY = [self createLabel:_originY :longitudeLabel :self];
[self addSubview:longitudeLabel];
_originY = [self createLabel:_originY :latitudeLabel :self];
[self addSubview:latitudeLabel];
}

You are observing text in a label, that is set only once in your didLoad method and it will never be updated after the location update. If you want to use observers you should observe your gpsModel instance and latitude/longitude properties in it. And in the observeValueForKeyPath delegate method you should update your text labels.

Related

ios device location course issue

I try to update device's location course real time.
I am doing some experiment, and i make the VC as CLLocationManager's delegate. But when i run the app, the course information is not updating at all. i did set up a breakpoint in the delegate setting line, but the location manager is nil from the debugging area.
What is the problem?
#import "CourseInfomationViewController.h"
#interface CourseInfomationViewController ()
- (IBAction)startMoveLocation:(id)sender;
#end
#implementation CourseInfomationViewController
{
CLLocationManager *_locationManager;
CLLocation *_deviceLocation;
double _deviceDirection;
double _altitude;
double _speed;
}
-(id)init {
if (self = [super init]) {
_locationManager = [[CLLocationManager alloc] init];
_locationManager.delegate = self;
_locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
//
_deviceLocation = [[CLLocation alloc] init];
}
return self;
}
- (IBAction)startMoveLocation:(id)sender {
[_locationManager startUpdatingLocation];
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - location Delegate
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
_deviceLocation = [locations lastObject];
_altitude = _deviceLocation.altitude;
_deviceDirection = _deviceLocation.course;
_speed = _deviceLocation.speed;
NSLog(#"altitude is %f", _altitude);
NSLog(#"altitude is %f", _deviceDirection);
NSLog(#"altitude is %f", _speed);
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(#"%#", error);
}

Why are my CLLocationManagerDelegate methods not called?

Calling class...
#implementation MenuViewController
- (void)viewDidLoad {
[super viewDidLoad];
FuelSiteLocator *siteLocator = [[FuelSiteLocator alloc]init];
[siteLocator getStations:#"Unleaded Regular"];
...
}
And this is the class that isn't working...
#implementation FuelSiteLocator {
CLLocationManager *locationManager;
}
-(id) initWithSearchType {
locationManager = [CLLocationManager new];
[locationManager setDelegate:self];
return self;
}
-(void) getStations:(NSString *)search {
[self setSearchType:search];
[locationManager startMonitoringSignificantLocationChanges];
}
-(void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
NSLog(#"%#", error.description);
}
-(void) locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
[self getGasStations:[locations lastObject]];
}
-(void) getGasStations:(CLLocation *) currentLocation {
NSLog(#"Hello Gas Stations..");
}
The delegate methods are not being called and I have no idea why... In FuelSiteLocator.h I'm using the CLLocationManagerDelegate protocol
****Problem Solved*******
ARC is releasing the siteLoactor object after getStations is called. The delegate methods never had a chance
As mentioned earlier in the comments, your init method is not correct.
try:
-(id) initWithSearchType:(NSString *)search {
self = [super init];
if (self) {
self.searchType = search;
self.locationManager = [CLLocationManager new];
self.locationManager.delegate = self;
}
return self;
}
(This assumes the class inherits from NSObject, as I haven't seen the class definition).

didUpdateToLocation is not called in app

I want to receive location updates. I have added a location delegate to the header file but didUpdateToLocation method not fire my code is
#interface FirstViewController : UIViewController <CLLocationManagerDelegate>
{
UILabel *myLabel;
CLLocationManager *manager;
CLGeocoder *geocoder;
CLPlacemark *placemark;
}
-(void) showCurrentLocation;
#end
and .m file like this:
#import "FirstViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
-(id) init
{
self=[super init];
if (self) {
self.view.backgroundColor=[UIColor purpleColor];
self.edgesForExtendedLayout=UIRectEdgeNone;
[self showCurrentLocation];
}
return self;
}
-(void) showCurrentLocation{
manager=[[CLLocationManager alloc] init];
manager.pausesLocationUpdatesAutomatically=NO;
geocoder=[[CLGeocoder alloc] init];
manager.delegate=self;
manager.desiredAccuracy=kCLLocationAccuracyBest;
}
-(void) locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSLog(#"Error %#",error);
NSLog(#"Faild to get location");
}
-(void) locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSLog(#"Location %#",newLocation);
CLLocation *currentlocation=newLocation;
if (currentlocation!=nil)
{
myLabel=[[UILabel alloc] initWithFrame:CGRectMake(30, 30, 200, 200)];
[myLabel setText:[NSString stringWithFormat:#"Latit %8f",currentlocation.coordinate.latitude]];
myLabel.textColor=[UIColor whiteColor];
[self.view addSubview:myLabel];
[geocoder reverseGeocodeLocation:currentlocation completionHandler:^(NSArray *placemark1 ,NSError *erroe){
if (erroe==nil && [placemark1 count]>0)
{
NSLog(#"Location");
}
else
{
NSLog(#"error 2 %#",erroe.debugDescription);
}
}];
}
}
You need to start location manager
manager = [CLLocationManager new];
manager.delegate = self;
[manager startUpdatingLocation]; // forgotten in the code above
Also be sure that you setup your scheme properly to simulate location in test mode via Simulator

Access to a class property dependent on asyncronous content

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

corelocation keeps looping

I essentially started off with this CoreLocation iOS tutorial to get my head around how to implement CoreLocation into my app. (http://www.techotopia.com/index.php/An_Example_iOS_5_iPhone_Location_Application)
But what I have encountered when trying to incorporate this tutorial into my app is that it now just keeps on looping over and over, which is just baffling me. Can anyone please help?
GPSViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface GPSViewController : UIViewController
#property (strong, nonatomic) CLLocationManager *locationManager;
#property (strong, nonatomic) CLLocation *startLocation;
#end
GPSViewController.m
#import "GPSViewController.h"
#import "DataClass.h"
#interface GPSViewController ()
#end
#implementation GPSViewController
#synthesize locationManager, startLocation;
DataClass *obj;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//initialization og global varable.
DataClass *obj=[DataClass getInstance];
//GPS Initialise
self.locationManager = [[CLLocationManager alloc] init];
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.delegate = self;
[locationManager startUpdatingLocation];
startLocation = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark -
#pragma mark CLLocationManagerDelegate
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSString *currentLatitude = [[NSString alloc]
initWithFormat:#"%g",
newLocation.coordinate.latitude];
//latitude.text = currentLatitude;
obj.Latatude = currentLatitude;
NSString *currentLongitude = [[NSString alloc]
initWithFormat:#"%g",
newLocation.coordinate.longitude];
//longitude.text = currentLongitude;
obj.Longitude = currentLongitude;
NSLog(#"latitude %+.6f, longitude %+.6f\n",
newLocation.coordinate.latitude,
newLocation.coordinate.longitude);
if(obj.Latatude != NULL && obj.Longitude != NULL){
[self performSegueWithIdentifier:#"GPSSuccess" sender:self];
}
}
-(void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.startLocation = nil;
self.locationManager = nil;
}
#end
You should call [locationManager stopUpdatingLocation]; in order to stop it from getting the user's location over and over.

Resources