i need to use a CLLocation - iphone

I need to read my position from GPS!
The problem is that i need to do out from the method
- (void)locationUpdate:(CLLocation *)location;
So... this is how i'm working:
in the .h file i have this
CLLocation *mylocation;
in the -viewDidLoad
mylocation = [[CLLocation alloc] init];
locationController = [[CLController alloc] init];
locationController.delegate = self;
[locationController.locationManager startUpdatingLocation];
then
- (void)locationUpdate:(CLLocation *)location {
mylocation = location;
}
and it works, if i use NSLog (on mylocation) i see my real location!
But... in another method (an IBAction connected with a UIButton) i want to use "mylocation"!
It's not working and i don't know why!
If, in this method, i try to do this
NSLog(#"%#", mylocation);
the console report this:
<+0.00000000, +0.00000000> +/- 0.00m (speed -1.00 mps / course -1.00) # 3/10/11 7:21:24 PM Central European Time
So the variable is empty!
Why??
PS= also in my IBAction i have, of course, this
mylocation = [[LCLocation alloc] init];
otherwise the app crashes!

This line:
mylocation = location;
Is setting mylocation's memory pointer to the one returned by the location manager, which later is getting released.
EDITED:
mylocation = [[CLLocation alloc] initWithLatitude:location.coordinate.latitude longitude:location.coordinate.longitude];

also in my IBAction i have, of course, this
mylocation = [[LCLocation alloc] init];
So you get zero values because you always overwrite your location value with newly created blank location - you should not do that.
The problem that makes your application crash is that in locationUpdate method you get autoreleased value, so in order to ensure that its valid outside of that method you must retain it. (and not forget to release old value). The easiest way to do that is create a property for myLocation ivar and access ivar using it:
// .h file
#property (nonatomic, retain) CLLocation *myLocation;
// .m
#synthesize myLocation;
...
- (void)locationUpdate:(CLLocation *)location {
self.mylocation = location;
}
- (void) dealloc{
[myLocation release];
myLocation = nil;
...
[super dealloc];
}

Related

Why can't I read the device's deviation from the magnetic North with this code?

OK the code is now working, but it still needs work. The values I get are "sticky", they are not stable (the magnetic North seems to move a bit every time I try to return to it), and I need to shake the device a bit in order to refresh/wake-up the values..
Game.h
#import <Foundation/Foundation.h>
#import "CoreLocation.h"
#interface Game : NSObject
<CLLocationManagerDelegate>
#property BOOL stopButtonPressed;
-(void) play;
#end
Game.m
#implementation Game
- (id) init
{
self = [super init];
self.stopButtonPressed = NO;
CLLocationManager *locationManager;
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
return self;
}
-(void) play
{
[locationManager startUpdatingHeading];
while(!self.stopButtonPressed)
{
double degrees = locationManager.heading.magneticHeading;
int degreesRounded = (int)degrees;
NSLog(#"Degrees : %i", degreesRounded);
}
}
#end
MyViewController.m
#interface MyViewController()
{
Game *game;
}
#end
#implementation MyViewController
-(void) viewDidLoad
{
game = [[Game alloc] init];
}
- (IBAction)playPressed:(UIButton *)sender
{
[game performSelectorInBackground:#selector(play) withObject:nil];
}
- (IBAction)stopPressed:(UIButton *)sender
{
game.stopButtonPressed = YES;
}
#end
What am I doing wrong?
This code will block the thread, and if it's happening in the main thread, you will never get the button press.
CLLocationManager is an asynchronous mechanism. To work with it properly, you must provide a delegate which it will notify when updates to location are available (this can be self in most cases (where self is a viewController or similar). See CLLocationManagerDelegate docs
...
CLLocationManager *locationManager;
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startUpdatingHeading];
}
- (void)locationManager:manager didUpdateHeading:newHeading {
double degrees = newHeading.magneticHeading;
NSLog(#"Degrees : %F", degrees);
}
You should catch the CLLocationManager delegate methods instead of calling the properties directly: https://developer.apple.com/library/mac/#documentation/CoreLocation/Reference/CLLocationManagerDelegate_Protocol/CLLocationManagerDelegate/CLLocationManagerDelegate.html#//apple_ref/occ/intf/CLLocationManagerDelegate

MKMapView - Removing annotation causes app crash

Removing annotations from my map view in the following way:
if ([[self.mapView annotations] count] > 0)
{
[self.mapView removeAnnotations:[self.mapView annotations]];
}
causes my application to crash with the following exception:
*** Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <MKAnnotationContainerView 0xe87b420> for the key path "title" from <PFAnnotation 0x10851230> because it is not registered as an observer.'
The annotations are added in the following way:
CLLocationCoordinate2D pinPosition;
for (int index = 0; index < [array count]; index++)
{
Station *aStation = [array objectAtIndex:index];
PFAnnotation *stationPin = [[PFAnnotation alloc] init]; //StationPinView
pinPosition = CLLocationCoordinate2DMake([[aStation valueForKey:#"latitude"] doubleValue], [[aStation valueForKey:#"longitude"] doubleValue]);
stationPin.stationName = [aStation valueForKey:#"stationName"];
stationPin.stationPosition = pinPosition;
stationPin.stationLength = [aStation valueForKey:#"platformLength"];
[self.mapView addAnnotation:stationPin];
[stationPin release];
}
My PFAnnotation.h is:
#interface PFAnnotation : NSObject <MKAnnotation>
{
NSString *stationName;
CLLocationCoordinate2D stationPosition;
NSNumber *stationLength;
}
#property (nonatomic, retain) NSString *stationName;
#property CLLocationCoordinate2D stationPosition;
#property (nonatomic, retain) NSNumber *stationLength;
#end
and my PFAnnotation.m is:
#implementation PFAnnotation
#synthesize stationName;
#synthesize stationPosition;
#synthesize stationLength;
- (CLLocationCoordinate2D)coordinate;
{
return stationPosition;
}
- (NSString *)title
{
return stationName;
}
- (NSString *)subtitle
{
if (stationLength == nil)
return nil;
else
return [NSString stringWithFormat:#"Platform Length: %#ft",stationLength];
}
- (void)dealloc {
[stationName release];
[stationLength release];
[super dealloc];
}
I have read in some other threads that, setting the annotation properties from background thread is the reason for the above error. But in my case,it is not so because every thing is performed on the main thread. Please advise.
ok..solved it at last!!! I think it was due to the animation provided during addition of annotations. since there were a number of annotations that were added back-to-back with animation and also the annotations were removed just before the animation started, there could have been a reference to the released annotation(this is my guess). Moreover, the removal+addition process was made on each regionDidChangeAnimated call, which could have made a overlap between the removal and addition process. Anyway, how I solved it was that, I provided a timer which will be fired only after 1 second after every regionDidchangeAnimated to make sure that the user has done with dragging. Thus unnecessary addition+removal of annotations was avoided and I was able to avoid the crash. Thanks to all guys here for their time taken to support me, especially Guntis Treulands.
In your PFAnnotation class, did you declare both title and subtitle properties as they are in the protocol?
http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MKAnnotation_Protocol/Reference/Reference.html
If Your PFAnnotation really has incorrect setters getters for string values:
from here: http://cocoadevcentral.com/d/learn_objectivec/
Setter:
- (void) setCaption: (NSString*)input
{
[caption autorelease];
caption = [input retain];
}
Getter:
- (NSString*) caption
{
return caption;
}
Release:
- (void) dealloc
{
[caption release];
[super dealloc];
}
also - it's easier to provide coordinates in this way: (also works on ios 3.1.3)
stationPin.stationPosition = (CLLocationCoordinate2D) {[[aStation valueForKey:#"latitude"] doubleValue], [[aStation valueForKey:#"longitude"] doubleValue]}
than (only from ios 4)
stationPin.stationPosition = CLLocationCoordinate2DMake([[aStation valueForKey:#"latitude"] doubleValue], [[aStation valueForKey:#"longitude"] doubleValue]);
Please check whether an explicit removal of observer to the property "title" is being done anywhere in the code.

Trying to pull properties from another class in iOS

I am completely new to iOS development so I may be doing this wrong but I have a class I am using to get coordinate gps data that I want to have as a generic class I can reuse in lots of apps. My problem is getting the data from the gps to properly display in other apps.
Here is my header file for the GPS class:
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#interface LocationAwareness : NSObject <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
}
#property(copy) NSString *longitude;
#property(copy) NSString *latitude;
#end
And here is the implementation:
#import "LocationAwareness.h"
#implementation LocationAwareness
#synthesize longitude;
#synthesize latitude;
- (id)init {
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; // whenever we move
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; // 100 m
[locationManager startUpdatingLocation];
return self;
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// Stops updating location if data has been updated within 10 minutes
if ( abs([newLocation.timestamp timeIntervalSinceDate: [NSDate date]]) < 600) {
[locationManager stopUpdatingLocation];
float latitudedata = newLocation.coordinate.latitude;
latitude = [NSString stringWithFormat:#"%f", latitudedata];
float logitudedata = newLocation.coordinate.longitude;
longitude = [NSString stringWithFormat:#"%f", logitudedata];
}
}
#end
Now I can't seem to find anywhere that tells me how to get the latitude or longitude properties in another project. I have the header imported and have tried to store LocationAwareness.latitude into a variable that I can use but everything I store it in ends up blank. When I start my main class and aloc init a locationawareness object the gps fires up so I think its working but I don't seem to know enough about how this works to get everything in order. I've been searching the internet for hours. Anyone have an idea what I am doing wrong?
Well, this may or may not be causing the problem (it's quite likely), but a major problem is your init method.
The beginning should be:
self = [super init];
if (self) {
// Do your initializing as you did above.
}
return self;
edit:
I added your code with my update to a project and it works well.
In order to use this, you should do something like the following:
LocationAwareness *loc = [[LocationAwareness alloc] init];
// Give it some time to start updating the current location and then
// in a different function:
NSLog(#"%#", loc.latitude);
EDIT 2
Wherever you are using this, you will want to declare a property which stores it so that you can create it once and reference it many times. To do that, use the following code:
In the header for the object where you want to use this object, add this with the other properties:
#property (nonatomic, assign) LocationAwareness *location;
Then, towards the top of your implementation file (.m file) you should see other #synthesize lines, add this one:
#synthesize location;
Then, create the actual location instance that you want to use as per the example above:
self.location = [[LocationAwareness alloc] init];
Now give it some time to figure out your location and start providing updates. Then you can print the location like this:
NSLog(#"%#", self.location.latitude);

Capturing current location and calculating distance

I've been looking at this for a while. I've found plenty of posts and looked at the documentation but I'm having trouble getting it working. I have core location implemented, and its working with no problems i.e.
NSLog(#"Description: %#\n", [newLocation description]);
The description details are displayed in the log.
I want to capture the current location when the user taps on a button and as they start to move recapture their location intermittently. Using this information I want to calculate the distance between the starting point and the current point.
I know I can use the following:
CLLocationDistance distance = [myLocation distanceFromLocation:restaurantLocation]
to calculate the distance but I'm not sure how to capture the current location.
If anyone could post some sample code that would be great. I close to getting this working, just need a final push over the line.
Regards,
Stephen
Part 2: Since the original post, I've made a bit of progess. Details posted below:
#import "MyCLController.h"
#implementation MyCLController
#synthesize locationManager;
#synthesize delegate;
- (id) init {
self = [super init];
if (self != nil) {
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self; // send loc updates to myself
}
return self;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
[self.delegate locationUpdate:newLocation];
CLLocation *item1 = [[CLLocation alloc] initWithLatitude:newLocation.coordinate.latitude longitude:newLocation.coordinate.longitude];
CLLocation *item2 = [[CLLocation alloc] initWithLatitude:oldLocation.coordinate.latitude longitude:oldLocation.coordinate.longitude];
int meters = [item1 getDistanceFrom:item2];
NSLog(#"Distance-d: %d", meters);
[item1 release];
[item2 release];
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
[self.delegate locationError:error];
}
- (void)dealloc {
[self.locationManager release];
[super dealloc];
}
#end
Am I right to calculate the distance here or should I be doing it in NewWorkoutViewController.m, in the locationUpdate method ?
You set a delegate on your location manager which will be called when the location changes. You can control (indirectly) how often it gets called by specifing a distance filter so that you will only get a callback if the location has moved at least that amount.

initializing the mapkit with a particular latitude and longitude Iphone

Iam making an iphone app, which should take in latitude and longitudes from an array and should locate and display the map with a customized annotation/pins. I have used the mapkit here's how:
//MapViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController <MKMapViewDelegate> {
IBOutlet MKMapView *mapView;
MKPlacemark *mPlacemark;
}
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
#end
//MapViewController.m
#import "MapViewController.h"
#import <MapKit/MapKit.h>
#implementation MapViewController
#synthesize mapView;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
CLLocationCoordinate2D location = mapView.userLocation.coordinate;
MKCoordinateRegion region;
MKCoordinateSpan span;
location.latitude = 37.250556;
location.longitude = -96.358333;
span.latitudeDelta = 0.05;
span.longitudeDelta = 0.05;
region.span = span;
region.center = location;
[mapView setRegion:region animated:YES];
[mapView regionThatFits:region];
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
[mapView setNeedsDisplay];
}
#end
This does not locate the place for the latitude and longitude. Please help.
I have made a sample project with your code and it works fine - map gets positioned to the expected (it seems) region. Check if your mapView ivar is initialized (are connections set properly in IB?)
Edit: In your code you just set map's visible region but do not add any annotations to it (apart from automatically showing current user position which is always in Cupertino if you test on simulator). To put pin to you map you need to create an object confirming to MKAnnotation protocol and add it to mapView:
// Sample example just to show annotation
// in your program you will likely need to use custom annotation objects
CLLocation* myLocation = [[CLLocation alloc] initWithLatitude:37.250556 longitude:-96.358333];
[mapView addAnnotation:myLocation];
Some (not so relevant) comments on your code:
You don't need to initialize location variable with current location as you overwrite its coordinate values immediately after that
Why do you call [mapView setNeedsDisplay]; in viewDidUnload method? I'm not sure if this may cause serious problems but you must use this method for cleaning memory up (e.g. releasing retained outlets), not for redrawing your UI
Have you set your map to follow user location somewhere else? maybe that default is overruling your manual movement of the map to Kansas.
edit
Do'h, didn't see this was July last year. Well maybe you could share your solution with us if this wasn't the problem