I'm making an app that determines a user's location and makes the [locationManager startUpdatingLocation] call in the initWithNibName function, but initWithNibName isn't being called right off the back so I added a call for it in the AppDelegate.m:
WhereamiViewController *wvc = [[WhereamiViewController alloc] initWithNibName:#"WhereamiViewController" bundle:nil];
This works, however then there is a problem with calling this function within the initWithNibName function: [locationManager startUpdatingLocation]. It literally returns nothing. But, if I change my code to call initWithNibName in my viewDidLoad line, it works. Why is this? I'm very confused and have been searching for answers but I'm at a standstill. I understand initWithNibName needs to be called, but I don't understand why it won't work if I call it from AppDelegate.m.
- (void)locationManager:(CLLocationManager *)manager
didUpdateLocations:(NSArray *)locations`
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
Here is my initWithNibName function:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer;
// Set a movement threshold for new events.
locationManager.distanceFilter = 500; // meters
[locationManager startUpdatingLocation];
}
return self;
}
you do have a Xib file set up right?
things to try:
if you are not using Nibs then create a method called init:
- (id) init {
self = [super init];
if(self) {
//call code here
}
return self;
}
and then instead of calling nib method in app delegate just call init
or second option would be to call the code straight in viewdidload instead of doing above
Related
i have been trying to implement the following code on my device:-
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface Whereami1ViewController : UIViewController<CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
__weak IBOutlet UILabel *coordLabel;
}
#end
#implementation Whereami1ViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
locationManager.distanceFilter= 5.00;//5 meters
[locationManager startUpdatingLocation];
}
return self;
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations{//location manager sends this message to self
NSLog(#"%#",NSStringFromSelector(_cmd));
NSLog(#"new location–– %#",[locations lastObject]);
NSLog(#"latitude= %f, longitude= %f",[[locations lastObject] coordinate].latitude, [[locations lastObject] coordinate].longitude);
CGSize coordData= {[[locations lastObject] coordinate].latitude, [[locations lastObject] coordinate].longitude};
coordLabel.text= NSStringFromCGSize(coordData);//setting the label's text
}
-(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error{
NSLog(#"%#",NSStringFromSelector(_cmd));
NSLog(#"location not found: %#", error);
}
#end
In the code i have set the distance filter as 5 meters. This means after 5 meters worth of movement the device goes through, it should be updating the label's text to a new coordinate,(latitude, longitude). But this is not happening in reality. I mean
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
should get called only when the device has moved more than 5 meters.In actuality, the device is stuck with the initial data (the label does not update in the view)..
What am i doing wrong.. Isn't this the right way??
The iPod touch uses WiFi networks for location service. So it may be impossible to get a good location or an update for 5 meter moves?! It ill behave quite different than an iPhone or iPda that also use GPS signals for location.
I'm trying to put everything location related inside a model. When I call this my MainViewController, the simulator doesn't ask me for my location, and nothing happens.
When I use the same code from my model, but put it directly in ViewDidLoad in my ViewController, everything works. I'm having a hard time understanding why.
Here is my model:
#implementation Location
{
CLLocationManager *_locationManager;
CLLocation *_location;
}
- (void)startLocationManager
{
NSLog(#"In startLocationManager");
_locationManager = [[CLLocationManager alloc] init];
_locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
_locationManager.delegate = self;
[_locationManager startUpdatingLocation];
}
#pragma mark - LocationManager Delegates
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
NSLog(#"In didUpdateLocations");
if (locations) {
_location = [locations lastObject];
NSLog(#"%#", _location);
}
}
#end
I call this in my MainViewController like this:
- (void)viewDidLoad
{
[super viewDidLoad];
Location *location = [[Location alloc] init];
[location startLocationManager];
}
Why does the code work like a charm directly in the viewController, but not through my model?
I figured it out.
I needed to make location a property of your view controller instead of a local variable in the viewDidLoad. Otherwise it is created and deallocated within that method. I need it to live through the lifecycle of my view controller.
I am using CLLocationManager class. I have a simple class method for capturing the location
+(void)captureLocation{
mLocationManager = [[CLLocationManager alloc]init];
mLocationManager.delegate = (id<CLLocationManagerDelegate>)self;
mLocationManager.desiredAccuracy = kCLLocationAccuracyBest;
[mLocationManager startUpdatingLocation];
}
and i have the delegate methods of CLLocationManager also
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
}
now i am trying to call this method in my viewDidLoad as
- (void)viewDidLoad
{
[super viewDidLoad];
[myclass captureLocation];
}
the method is getting called but the delegate methods are not getting called.
I have other class method also and from there if I try to call the method again the captureLocation method is getting called but the delegate methods are not called. Here is the other class method
+(void)initialize{
[self captureLocation];
}
please help me to find out why delegate methods are not getting called as I am new to this field. Thanks in advance.
Also know that CoreLocation permissions have changed with iOS 8. If you don't request the new permissions authorizations, CoreLocation doesn't do anything. It fails quietly because the delegate methods are never called.
I realize this question was asked in 2013, but if you are having a similar problem with the delegate methods not getting called, this article is extremely helpful:
http://nevan.net/2014/09/core-location-manager-changes-in-ios-8/
While the article is very detailed and long, the actual code fix can be as minor as this:
if ([locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[locationManager requestWhenInUseAuthorization];
}
And you have to add a value to info.plist, which is the message to display in the permissions alert. See screen grab.
Key: NSLocationWhenInUseUsageDescription
Value: Location is required to find out where you are (You can change that to whatever you want)
You are setting the delegate of the CLLocationManager inside a class method (i.e. one prefixed by + rather than -). So, when you reference self within that class method, that's the class, not an instance of the class. So, you are trying to set the delegate to the class rather than an instance of the class.
That won't work. The delegate methods are instance methods, not class methods. (This is presumably why you had to use the CLLocationManagerDelegate cast when assigning the delegate.)
You must actually instantiate whichever class you've implemented the CLLocationManagerDelegate methods. If you don't want to tie that instance to a particular view controller, you could use a singleton pattern. Regardless, you can set the location manager's delegate to point to that instance of that class.
For example, if you wanted it to be a singleton:
// MyClass.h
#import <Foundation/Foundation.h>
#interface MyClass : NSObject
+ (instancetype)sharedManager;
- (void)startCapture;
- (void)stopCapture;
#end
and
// MyClass.m
#import "MyClass.h"
#import <CoreLocation/CoreLocation.h>
#interface MyClass () <CLLocationManagerDelegate>
#property (nonatomic, strong) CLLocationManager *locationManager;
#end
#implementation MyClass
+ (instancetype)sharedManager
{
static id sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (void)startCapture
{
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[self.locationManager startUpdatingLocation];
}
- (void)stopCapture
{
[self.locationManager stopUpdatingLocation];
self.locationManager = nil;
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
// ...
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
// ...
}
#end
And then,
- (void)viewDidLoad
{
[super viewDidLoad];
[[MyClass sharedInstance] startCapture];
}
Calling self in a + method set your delegate to nil as it means ClassName as in [[ClassName alloc] init].
you need to:
mLocationManager.delegate = mLocationManager
instead of
mLocationManager.delegate (id<CLLocationManagerDelegate>)self;
in ios6 locationManager:didUpdateToLocation:fromLocation: is deprecated so you need to add another method in your code ...
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
// this method get called in ios7 .
}
In iOS -8 need to do some changes :
Please have a look into this :Get current location in iOS-7 and iOS-8
I am making a simple map app - I am sending and receiving locations and text on a pubnub channel. When a chat message comes in, I want to use a simple MKAnnotation to draw the chat (I'm aware this is a horrifying act of UX and I don't care).
When my app delegate receives a message on the pubnub channel, it calls a method in the main view controller to draw the text message on the map. The method should use the latest user location for the pin's coordinates.
I'm not sure why, but I can't get the annotation to show from within my method. I have tried building the annotation from within the method and showing it. I've also tried making a custom annotation class and calling it from within my method. When I use the very same annotation code but hardcode it in my viewDidLoad then it shows up just fine. Any insight would be most appreciated.
My App Delegate:
#import "MyLocationAppDelegate.h"
#import "MyLocationViewController.h"
#implementation MyLocationAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[PubNub setDelegate: self];
return YES;
}
- (void)pubnubClient:(PubNub *)client didReceiveMessage:(PNMessage *)message
{
NSString* text = message.message;
//Call drawChat method of MyLocationViewController
MyLocationViewController *MyLocViewController = [[MyLocationViewController alloc] init];
[MyLocViewController drawChat:text];
}
My View Controller:
#import "MyLocationViewController.h"
#import "MyLocationAppDelegate.h"
#import "MyLocationAnnotation.h"
CLLocation *userLocation;
#implementation MyLocationViewController {
CLLocationManager *locationManager;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//Delegate map view
self.mapView.delegate = self;
[self SetUpChat];
[self configurePubNub];
//Instantiate location manager
if (nil == locationManager) {
locationManager = [[CLLocationManager alloc] init];
}
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
NSLog(#"Application: viewDidLoad");
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
userLocation = [locations lastObject];
}
- (void)drawChat:(NSString *)message
{
//Create new annotation object
CLLocationCoordinate2D location;
location.latitude = userLocation.coordinate.latitude;
location.longitude = userLocation.coordinate.longitude;
MyLocationAnnotation *chat = [[MyLocationAnnotation alloc] initWithLocation:location andTitle:message];
[self.mapView addAnnotation:chat];
}
And MyLocationAnnotation.m
#import "MyLocationAnnotation.h"
#implementation MyLocationAnnotation
- (id)initWithLocation:(CLLocationCoordinate2D)coord andTitle:(NSString *)ttl {
self = [super init];
if (self) {
_coordinate = coord;
_title = ttl;
}
return self;
}
#end
Thanks to Anna's pointing out what I was doing wrong I was able to fix this:
Instead of redclaring my main view controller in the app delegate I did this instead:
MyLocationViewController *mainController = (MyLocationViewController *) self.window.rootViewController;
[mainController drawChat:text];
I was then able to call the method just fine with the data from app delegate.
I have the following code in my ViewController:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
int desiredHA = 200;
RemoteDataController *rdc = [[RemoteDataController alloc]init];
double ha = newLocation.horizontalAccuracy;
if (ha <= desiredHA)
{
[rdc addLoc];
[self.locationManager stopUpdatingLocation];
return;
}
}
-(void)startLogging
{
if(self.locationManager==nil)
{
self.locationManager=[[CLLocationManager alloc] init];
self.locationManager.delegate = self;
self.locationManager.desiredAccuracy=kCLLocationAccuracyBest;
self.locationManager.distanceFilter=kCLDistanceFilterNone;
}
if([CLLocationManager locationServicesEnabled])
{
NSLog(#"Start Location Tracking");
[self.locationManager startUpdatingLocation];
}
}
-(void)addLocResponse
{
NSLog(#"send checkin response");
self.silenceTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self
selector:#selector(onTick:) userInfo:nil repeats:NO];
}
-(void)onTick:(NSTimer *)timer
{
[self startLogging];
}
Then my RemoteDataController.m file looks like this:
#implementation RemoteDataController
-(void)addLoc
{
ViewController *vc = [[ViewController alloc]init];
[vc addLocResponse];
NSLog(#"Add Loc");
}
#end
I know this looks stupid right now but I stripped out a lot of the details of it so it's not too complicated.
My question is when I call addLocResponse from the RemoteDataController class the timer runs and then hits the onTick which fires of startLogging again. I can see it's running startLogging again from the NSLog but it does not run the locationManager delegate again.
If I keep all this in the ViewController it works fine but when I try to go out to RemoteDataController and back it does not work.
I am just trying to figure out what I am doing wrong here.
This is iOS6.
Any help would be great.
Thanks in advance!
You are not using a correct initializer for your view controller. Also, put a breakpoint on the dealloc method of your ViewController instance. Chances are it's being deallocated (if you are using ARC) because you are not doing anything with it (modal presentation or push).