I have a CLLocation that I set to the current location within the following function
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation{
currentLocation = newLocation;
}
When I try to access the current position in a later method the app crashes.
NSLog(#"current latitude is %f", currentLocation.coordinate.latitude);
NSString *longitude = [NSString stringWithFormat:#"%g", currentLocation.coordinate.longitude];
NSString *latitude = [NSString stringWithFormat:#"%g", currentLocation.coordinate.latitude];
The current position is set in the first method. I can print it out, what is weird is that I have this currentLocation defined as a pointer in the header.
The app crashes and there is no stacktrace. The debugger just sends me to the retValue of my app.
I tried retaining the pointer as well as alloc before setting it to the newLocation, but nothing seems to work.
What am I missing :D
I'm not so sure about your code but I can suggest this
I tried retaining the pointer as well as alloc before setting it to the newLocation, but nothing seems to work.
You need to retain newLocation pointer not the currentLocation before setting.
currentLocation = [newLocation retain];
or
self.currentLocation = newLocation;
Because your assignment currentLocation = newLocation; does not retain the pointer and newLocation is autorelease.
The app crashes and there is no
stacktrace. The debugger just sends me
to the retValue of my app.
Are you using Xcode 4? A lot of people are having trouble with the new interface. At the bottom of the stack trace window there's a slider, if it's set to be "coarse" it'll only show the app's main() block.
As indicated in the comments above, I reckon you should be saying self.currentLocation instead of currentLocation. The difference is that when you just say currentLocation, you are only assigning a pointer. To get all the "magic" functionality that you define in the header file (retain, et al), you need to use the self.currentLocation notation, OR, [self setCurrentLocation:newLocation];. Functionally those are the same, it's a matter of style.
Related
in my app in map view i want to show the nearest 10 stores for the user's current location
but first i have to take current location first then i can show the stores according to user's location
in first start of the app the app ask user if he allow to get current location or not so i must do something like
if user allow
list stores on map
else
go back to main page
now i am using the code below:
mtMap.showsUserLocation=YES;
mymanager=[[CLLocationManager alloc] init];
mymanager.delegate=self;
CLLocation *location = [mymanager location];
CLLocationCoordinate2D coordinate2 = [location coordinate];
NSString *latitude1 = [NSString stringWithFormat:#"%f", coordinate2.latitude];
NSString *longitude1 = [NSString stringWithFormat:#"%f", coordinate2.longitude];
NSString *myURL = [[NSString alloc] initWithFormat:#"http://www.xxxx.com/xxxx/aaaaa.ashx?term=%#,%#",latitude1,longitude1];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:myURL]];
NSInputStream *dataStream=[[NSInputStream alloc]initWithData:data];
[dataStream open];
if(dataStream)
{
NSError *err=nil;
id jsonobject=[NSJSONSerialization JSONObjectWithStream:dataStream options:NSJSONReadingAllowFragments error:&err];
if([jsonobject respondsToSelector:#selector(objectForKey:)])
{
//fill arr
}
}
but it doesn't work for the first time when the user opens the app because of late allowing or getting current location late i can't reach where he is so i can't show nearest places
there can be a problem with my logic. i mean may be i shouldn't do all the job in viewDidload
so could anyone help how can i solve this problem?
Instead of doing it under the viewDidLoad section, what about inserting the code in this method?
// Delegate method from the CLLocationManagerDelegate protocol.
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
CLLocation *location = newLocation;
...
That would make the code run once the user's location was updated.
You could also add an if statement inside the method to check if it is the first time the code has been run and if not to return.
In my appDelegate I am using LocationManager :
- (void)locationManager: (CLLocationManager *)manager
didUpdateToLocation: (CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
float latitude = newLocation.coordinate.latitude;
strLatitude = [NSString stringWithFormat:#"%f",latitude];
float longitude = newLocation.coordinate.longitude;
strLongitude = [NSString stringWithFormat:#"%f", longitude];
[self CheckOperation];
}
strLatitude and strLongitude are global strings. This is absolutely fine. Even on analyzing the application I don't get any memory leak. But when I profile my application I receive a memory leak at
strLatitude = [NSString stringWithFormat:#"%f",latitude];
and
strLongitude = [NSString stringWithFormat:#"%f", longitude];
of 32 bytes.
How can I fix that?
Are you sure you're seeing a leak and not simply just an allocation?
If you do actually have a leak here then there are some potential suspects:
Are you using ARC? If not, here are some possible problems:
Are you releasing it in dealloc?
If this method gets run more than once, you aren't releasing the last value before you reassign it.
If you're not using copy semantics, and you're passing this string reference off to someone else, and they aren't properly releasing it, you'll also get a backtrack to this line.
EDIT:
(Per the comments below)
You should realize that stringWithFormat: is allocating a string and queuing up an autorelease on it... so you need to retain it somewhere.
I assumed you were doing this somewhere because you aren't getting an "EXC_BAD_ACCESS" - but rather, supposedly, a leak.
You shouldn't be leaking an autoreleased object unless you've retained it somewhere (hence the assumption).
Given you need to be retaining it somewhere, my above suggestions are valid - each retain needs a matching release.
I do agree that you should be using properties for these strings.
It's simple to convert them - and takes care of a lot of things for you.
In your Interface:
#property (nonatomic, copy) NSString * strLatitude;
In your Implementation:
#synthesize strLatitude;
To assign:
self.strLatitude = ...
(the "self." part is important)
And make sure you set that to nil in dealloc.
i'm having trouble sending my position when the application lies in the background. I'm using CLLocationManager and startMonitoringSignificantLocationChanges. The posision didUpdateToLocation delegate method is performed once, but not more. I've tried to walk around but no new locations is sent to the server.
I have set the "Required background modes" -> "App registers for location updates" in the info.plist file.
Anyone got an idea on what might be wrong?
Code from where the tracking is started:
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = appDelegate;
[appDelegate setLocationManager:locationManager withDistanceFilter:kCLDistanceFilterNone];
[appDelegate.theLocationManager startMonitoringSignificantLocationChanges];
Code (from CLLocationManagerDelegate):
- (void)setLocationManager:(CLLocationManager*)locationManager withDistanceFilter:(CLLocationDistance)distanceFilter {
// create a new manager and start checking for sig changes
self.theLocationManager.delegate = nil;
[theLocationManager release];
self.theLocationManager = locationManager;
self.theLocationManager.delegate = self;
self.theLocationManager.distanceFilter = distanceFilter;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
NSDate *newLocationTimestamp = newLocation.timestamp;
NSDate *oldLocationTimestamp = oldLocation.timestamp;
int locationUpdateInterval = 15;//15 sec
if (!([newLocationTimestamp timeIntervalSinceDate:oldLocationTimestamp] < locationUpdateInterval)) {
//NSLog(#"New Location: %#", newLocation);
[self updateToLocation:newLocation];
}
}
- (void)updateToLocation:(CLLocation *)newLocation {
NSLog(#"update location!!");
NSString *latitude = [NSString stringWithFormat:#"%f", [newLocation coordinate].latitude];
NSString *longitude = [NSString stringWithFormat:#"%f", [newLocation coordinate].longitude];
[currentUser updatePositionWithLongitude:longitude andLatitude:latitude];
}
Like Bill Brasky said, the accuracy to which you have set your location manager is likely not registering the distance that you have walked. Try setting your location manager accuracy much higher, just to see if works, then dial it back down to a happy medium between accuracy and battery efficiency. Just for testing, take it all the way up:
[appDelegate.theLocationManager setDesiredAccuracy:kCLLocationAccuracyBestForNavigation];
Then instead of:
[appDelegate.theLocationManager startMonitoringSignificantLocationChanges];
try:
[appDelegate.theLocationManager startUpdatingLocation];
The -startMonitoringForSignificantLocationChanges is directly tied to cell tower connectivity. You may need to travel miles to get connection to a new tower and trigger a location change event. I know that the region monitoring is a bit more accurate as it uses updates of location from Wifi, cell tower, and even other apps that inquire on location. You will need to figure out how accurate and how often you need your app to be. You may need to actively monitor location in the background (which would be a battery killer for sure). Hope this helps.
I am getting a EXC_BAD_ACCESS signal when calling the following line:
self.distance = [NSNumber numberWithDouble:[currentLocation distanceFromLocation: self.location]];
This is only happening in iOS 3.2 for iPad,
I know this is a memory issue but i can't seem to see what is wrong with the above line?
edit: here is the full method:
-(void)updateDistance:(CLLocation *)currentLocation {
self.distance = [NSNumber numberWithDouble:[currentLocation distanceFromLocation:self.location]];
placeWrapper.distance = self.distance;
}
which is called like so:
[place updateDistance:self.currentLocation];
self.currentLocation is created here:
CLLocation *location = [[CLLocation alloc] initWithLatitude:newLocation.coordinate.latitude longitude:newLocation.coordinate.longitude];
self.currentLocation = location;
[location release];
Another edit :)
here is the stack trace: http://pastie.org/1222992
Run your code with NSZombieEnabled set. This should tell you if you are over releasing or under retaining somewhere.
It's difficult to say without demonstrating where/how you're creating "currentLocation", "location", or possibly even "self". I'm guessing either currentLocation or self.location are not properly retained on creation/setting.
You need to retain something...
[currentLocation retain]
or
[self.location retain];
but you have to do it further up the code. Something's getting "forgotten" or goes "out of scope" so try those retains.
DON'T FORGET TO RELEASE WHATEVER IT IS THAT YOU'RE RETAINING.
I am using the CLLocationManger to update the current location. Though its giving me the location but the location I am getting is of much older timestamp. I am facing the problem in, how to force the locationcontroller to update the fresh location not the cached location.
Currently I am using this tutorial......
http://www.mobileorchard.com/hello-there-a-corelocation-tutorial/
Anybody know how to update location at current timestamp not the cached one?
Are you running your project on simulator or on iPhone? If you are running project on simulator then
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
will be called only once.
If you are testing on device then it should be called everytime your location is changed.
Make sure you have set the location manager property,
locationManager.delegate=self;
[locationManager startUpdatingLocation];
Hope that helps...
you can use this methods
- (IBAction)update {
locmanager = [[CLLocationManager alloc] init];
[locmanager setDelegate:self];
[locmanager setDesiredAccuracy:kCLLocationAccuracyBest];
NSLog(#"*********this is location update method of login view controller");
[locmanager startUpdatingLocation];
}
-(void)awakeFromNib {
[self update];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
if (wasFound) return;
wasFound = YES;
CLLocationCoordinate2D loc = [newLocation coordinate];
lat2 = [[NSString stringWithFormat: #"%f", loc.latitude]retain];
logg2= [[NSString stringWithFormat: #"%f", loc.longitude]retain];
NSLog(#"latitude is %#",lat2);
NSLog(#"longitude is %#",logg2);
}
call the update method using perform selector in viewdidload method.Here lat2 and logg2 are string values.
if problem can't be solved then type how to find current location in google.you will get many examples source code with explanation
The best you can do is throw out locations that are too old by whatever standard you decide to set for your app. Restarting the location manager is supposed to tell the system you want a new location, but usually the first location you get back may be whatever it had last. Checking the timestamp may be all you can do, but be prepared for the possibility that you may never get a newer location. I've seen in my experience that if the device hasn't moved, it never bothers to update the system with a new location if it detects that the current location is good enough.