objective-c locationManager as delegate, be notified if location changed - ios

I sourced my locationManager out in a own class and file
Now I want to be notified when the location is updated. So I tried to implement the delegation pattern. But for some reason it does not work. What I did:
In Location.h: specified class, protocol, ivar and property id, delegation method
In Location.m: added a call to the delegation method
In ViewController.h: added delegation protocol
In ViewController.m: implemented the delegation method
Build and run the code. But the delegation method in ViewController.m is not called :(
Any ideas what i missed?
Output
2013-07-04 11:55:30.429 Sandbox2[2001:c07] Inside Lokation::getLocation
2013-07-04 11:55:30.443 Sandbox2[2001:c07] Inside Lokation::locationManager
2013-07-04 11:55:30.449 Sandbox2[2001:c07] currentLat: 51.509980 currentLng -0.133700
// Missing NSLog Statement of the delegate method didFindLocation...
ViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
// added Lokation header
#import "Lokation.h"
// added LokationDelegate
#interface ViewController : UIViewController <CLLocationManagerDelegate, LokationDelegate>
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#property (strong, nonatomic) Lokation *lokation;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//[self getLocation];
self.lokation = [[Lokation alloc] init];
self.lokation.delegate = self;
[self.lokation getLocation];
}
// added delegate function of Lokation
// Should be run after the locationmanager found a location
-(void)didFindLocation {
NSLog(#"I am found a lokation and I am now in the ViewController");
}
Lokation.h (20130704 updated to working code)
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
// Added class, protocol and method for the delegate
#class Lokation;
#protocol LokationDelegate <NSObject>
-(void)didFindLocation;
#end
#interface Lokation : NSObject <CLLocationManagerDelegate> {
CLLocationDegrees currentLat;
CLLocationDegrees currentLng;
}
#property (strong, nonatomic) CLLocationManager *locationManager;
#property (nonatomic, strong) CLLocation *currentLoc;
// added delegate property
#property (assign, nonatomic) id<LokationDelegate> delegate;
-(void)getLocation;
#end
Lokation.m (20130704 updated to working code)
#import "Lokation.h"
#implementation Lokation
#synthesize locationManager = _locationManager;
#synthesize currentLoc = _currentLoc;
-(void)getLocation {
NSLog(#"Inside Lokation::getLocation");
// active location determination
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
// We don't want to be notified of small changes in location,
// preferring to use our last cached results, if any.
self.locationManager.distanceFilter = 50;
[self.locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog(#"Inside Lokation::locationManager");
if (!oldLocation ||
(oldLocation.coordinate.latitude != newLocation.coordinate.latitude &&
oldLocation.coordinate.longitude != newLocation.coordinate.longitude)) {
currentLat = newLocation.coordinate.latitude;
currentLng = newLocation.coordinate.longitude;
} else { // oldLocation
currentLat = oldLocation.coordinate.latitude;
currentLng = oldLocation.coordinate.longitude;
}
self.currentLoc = [[CLLocation alloc] initWithLatitude:currentLat longitude:currentLng];
NSLog(#"currentLat: %f currentLng %f", currentLat, currentLng);
// added call to the delegate function
[self.delegate performSelector:#selector(didFindLocation)];
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error {
NSLog(#"%#", error);
}

Hmm..i think you are doing right but if i do change like below:
remove __unsafe_unretained id<LokationDelegate> delegate; and replace #property (assign, nonatomic) id<LokationDelegate> delegate with #property (retain) id<LokationDelegate> delegate (and synthesize property),it works like charm for me

Related

IOS CLLocation manager returning zero speed

Hi I want to calculate speed within my camera view in XCODE8. The code does not generate error but my speed is returning zero. So I searched the link below :Self Location Manager Delegate error in Xcode 6. My code has two interface files, one for CvVideoCamera and one for ClLocationManager. I never had two interface files in my project, so I am not sure I am doing everything correctly. My code is below, Can you please tell me if something is wrong in my code architecture that causing me to get zero speed.
viewcontroller.h
#interface ViewController : UIViewController<CvVideoCameraDelegate>
#property (nonatomic, strong) CvVideoCamera* videoCamera;
…
#end
#interface LocationController : UIViewController <CLLocationManagerDelegate>
#property (strong, nonatomic) CLLocationManager*locationManager;
#end
viewcontroller.m
#import "ViewController.h"
int speed;
#interface LocationController() {
}
#end
#implementation LocationController
#synthesize locationManager;
- (void)viewDidLoad
{
[super viewDidLoad];
self.locationManager = [[CLLocationManager alloc] init];
[self.locationManager startUpdatingLocation];
self.locationManager.delegate = (id)self;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
CLLocation *loc = locations.lastObject;
loc = locations.lastObject;
speed = loc.speed * 2.236;
}
#end
#interface ViewController (){
….
}
#end
#implementation ViewController
#synthesize imageView;
#synthesize videoCamera
- (void)viewDidLoad
{
[super viewDidLoad];
self.videoCamera.delegate = self;
(void)processImage:(cv::Mat&)image {
NSLog(#"speed: %.d”, speed)}

Objective-C CLLocationManager is nil all of a sudden

I am using CLLocationManagerDelegate
I have done the following in my .h file:
#import <UIKit/UIKit.h>
#import <ExternalAccessory/ExternalAccessory.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController <DTDeviceDelegate, AVAudioPlayerDelegate, CLLocationManagerDelegate, UIAlertViewDelegate>
{
CLLocation *currentLocation;
}
#end
and here is my .m file:
#import "ViewController.h"
#interface ViewController ()
{
AVAudioPlayer *_audioPlayer;
}
#end
#implementation ViewController
{
CLLocationManager *locationManager;
}
- (void)viewDidLoad {
[super viewDidLoad];
currentLocation = nil;
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *) newLocation fromLocation:(CLLocation *)oldLocation
{
if (currentLocation == nil)
currentLocation = newLocation;
if (currentLocation != nil) {
Long.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.longitude];
Lat.text = [NSString stringWithFormat:#"%.8f", currentLocation.coordinate.latitude];
}
}
#end
I put break points in viewDidLoad and in didUpdateToLocation in viewDidLoad it says locationManager is nil and my break points in didUpdateToLocation do not get hit, this was working before. All of a sudden it does not work.
NSLocationAlwaysUsageDescription and NSLocationWhenINUseUsageDescription and privacy - location usage description and defined in my .plist file.
Two problems. You have the locationManager ivar declared in both the header file and in the class implementation. Remove it from the header file.
The real big issue is that you never create the location manager.
In viewDidLoad you need:
locationManager = [[CLLocationManager alloc] init];
On a side note, you should remove all of the protocols from the #inteface line in the header file and add them to the #interface line in the .m (for the class extension).
In other words, the .h should be:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#end
And the .m should be:
#import "ViewController.h"
#import <ExternalAccessory/ExternalAccessory.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController () <DTDeviceDelegate, AVAudioPlayerDelegate, CLLocationManagerDelegate, UIAlertViewDelegate>
{
AVAudioPlayer *_audioPlayer;
}
#end
#implementation ViewController
{
CLLocationManager *locationManager;
}
// and the rest
There is no reason to put all of those private details in the public header file.

Connecting a viewcontroller to a delegate class - CLLocationManager / iOS8

While trying to link my view controller to a delegate class (that implements CLLocation call backs), I am getting an error when initializing my delegate.
My VC.h:
#interface ViewController : UIViewController <MyLocationControllerDelegate> {
MyLocationController *CLController;
}
Instantiating MyLocationController in the main VC.m:
CLController = [[MyLocationController alloc] init];
CLController.locationManager.delegate = self;
[CLController.locationManager requestWhenInUseAuthorization];
CLController.locationManager.distanceFilter = kCLDistanceFilterNone;
CLController.locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;
[CLController.locationManager startUpdatingLocation];
The class header file:
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#protocol MyLocationControllerDelegate;
#interface MyLocationController: NSObject {
CLLocationManager *locationManager;
__weak id delegate;
}
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, weak) id delegate;
#end
and .m file (where I get the error):
- (id)init
{
self = [super init];
if(self != nil) {
self.locationManager = [[CLLocationManager alloc] init]; // Create new instance of locationManager
self.locationManager.delegate = self; // Set the delegate as self.
}
return self;
}
I noticed that this error does not show up in previous iOS versions.
Thanks for the help.
According to the documentation, MyLocationController must conform to CLLocationManagerDelegate.
#interface MyLocationController: NSObject <CLLocationManagerDelegate>
#property (nonatomic, strong) CLLocationManager *locationManager;
#property (nonatomic, weak) id delegate;
#end
As a side note, you don't need to declare the iVars for the properties locationManager and delegate. The iVars _locationManager and _delegate will be auto generated for you.

custom delegate method only gets called in one class

Why is my delegate method only called in MainViewController and not in MapViewController?
LocationService.h
#protocol LocationServiceDelegate <NSObject>
#optional
- (void) currentLocation: (CLLocation*) location;
#end
#property (nonatomic, assign) id delegate;
LocationService.m
if ([delegate respondsToSelector:#selector(currentLocation:)])
{
[delegate currentLocation:newLocation];
}
Here the method get called (in MainViewController)
MainViewController.h
#import "LocationService.h"
#interface MainViewController : UIViewController <LocationServiceDelegate>
MainViewController.m
locationService = [[LocationService alloc] init];
locationService.delegate = self;
- (void) currentLocation: (CLLocation*) location
{
// some code, this method get called perfectly
}
And in my other class, the same procedure wont work
MapViewController.h
#import "LocationService.h"
#interface MapViewController : UIViewController <MKMapViewDelegate, LocationServiceDelegate>
MapViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
locationService =[[LocationService alloc] init];
locationService.delegate = self;
}
- (void)currentLocation:(CLLocation *)location
{
// this method does not get called
}
Cheers!
Are you setting delegate to nil somewhere as the code looks fine to me? Please use break pointer to see if it step into currentLocation method implementation in MapViewController.

How to call a variable from another class

First off, do you guys know of any good tutorial sites or books to learn how to code for iOS6?
Now to the problem at hand, I have an AppDelegate class and a ViewController class.
I am using the AppDelegate class to find my current location and save it as an NSString.
I have a label in my ViewController class where I want to display my location.
In java I would usually just do something like this
label.text = AppDelegate.myLocationString;
But I am fairly new to objective c and I don't know how to do the equivalent. To be honest I'm not even sure if I am taking the correct approach for this language. Is there another way to approach this problem in objective c?
I've tried searching around for how to do it but I'm not even sure that I'm phrasing my searches correctly so I don't know if I'm searching in the right direction.
Any help that could be offered would be very much appreciated
My code as it is now:
AppDelegate.h
#import <UIKit/UIKit.h>
#import CoreLocation/CoreLocation.h
#class BIDViewController;
#interface BIDAppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) BIDViewController *viewController;
#property (strong, nonatomic) CLLocationManager *locationManager;
#property (strong, nonatomic) NSString *myPosition;
#end
LocationManager class from AppDelegate.m
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSDate *eventDate = newLocation.timestamp;
NSTimeInterval howRecent = [eventDate timeIntervalSinceNow];
if (abs(howRecent) < 15) {
//if it is within the last 15 seconds, use it. Else do nothing.
if (newLocation.horizontalAccuracy < 35.0) {
//location seems pretty accurate so we will use it
NSLog(#"latitude: %+.6f, longitude: %+.6f\n", newLocation.coordinate.latitude, newLocation.coordinate.longitude);
NSLog(#"Horizontal accuracy: %f", newLocation.horizontalAccuracy);
int latDegrees = newLocation.coordinate.latitude;
int lonDegrees = newLocation.coordinate.longitude;
double latDecimal = fabs(newLocation.coordinate.latitude - latDegrees);
double lonDecimal = fabs(newLocation.coordinate.longitude - lonDegrees);
int latMinutes = latDecimal * 60;
int lonMinutes = lonDecimal * 60;
double latSeconds = ((latDecimal * 3600) - (latMinutes * 60));
double lonSeconds = ((lonDecimal * 3600) - (lonMinutes * 60));
_myPosition = [NSString stringWithFormat:#"Lat: %d, %d, %1.4f, Lon: %d, %d, %1.4f", latDegrees, latMinutes, latSeconds, lonDegrees, lonMinutes, lonSeconds];
}
}
}
ViewController.h
#import <UIKit/UIKit.h>
#interface BIDViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *positionLabel;
#end
ViewController.m
#import "BIDViewController.h"
#import "BIDAppDelegate.h"
#interface BIDViewController ()
#end
#implementation BIDViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//I have tried setting the label's text here but to no avail so far, I have been
//able to set it as "blah" with the following line:
//
// positionLabel.text = #"blah";
//
//and I have tried things such as the following to populate the label with the
//myPosition variable:
//
// positionLabel.text = _myPosition;
// or
// positionLabel.text = AppDelegate._myPosition;
}
- (void)viewDidUnload
{
[self setPositionLabel:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
To reference the App Delegate from your view controller, first import its definition (which you've ready done):
#import "BIDAppDelegate.h"
and then in code get the delegate:
BIDAppDelegate *appDelegate = (BIDAppDelegate *)[[UIApplication sharedApplication] delegate];
and then get the location from the delegate:
CLLocation *location = appDelegate.locationManager.location;
and then call whatever method you like on the location object:
NSString *descr = location.description;
Or get the pre-calculated position with:
NSString *position = appDelegate.myPosition;
In your ViewController
BIDAppDelegate *appDelegate = (BIDAppDelegate *)[UIApplication sharedApplication].delegate;
[positionLabel setText:appDelegate.myPosition];
How to call a variable from another class?
Assume you are in ClassB
ClassA *aObj=... ; //create an object of ClassA
aObj.propertyName=...;//set the property or ivar
NSString *string=aObj.propertyName;//retrieve it
do you guys know of any good tutorial sites or books to learn how to
code for iOS6?
http://www.lynda.com/Apple-training-tutorials/106-0.html
http://www.raywenderlich.com/tutorials

Resources