NSMutableArray of ClLocationCoordinate2D - iphone

I'm trying to create then retrieve an array of CLLocationCoordinate2D objects, but for some reason the array is always empty.
I have:
NSMutableArray *currentlyDisplayedTowers;
CLLocationCoordinate2D new_coordinate = { currentTowerLocation.latitude, currentTowerLocation.longitude };
[currentlyDisplayedTowers addObject:[NSData dataWithBytes:&new_coordinate length:sizeof(new_coordinate)] ];
I've also tried this for adding the data:
[currentlyDisplayedTowers addObject:[NSValue value:&new_coordinate withObjCType:#encode(struct CLLocationCoordinate2D)] ];
And either way, the [currentlyDisplayedTowers count] always returns zero. Any ideas what might be going wrong?
Thanks!

To stay in object land, you could create instances of CLLocation and add those to the mutable array.
CLLocation *towerLocation = [[CLLocation alloc] initWithLatitude:lat longitude:lon];
[currentDisplayedTowers addObject:towerLocation];
To get the CLLocationCoordinate struct back from CLLocation, call coordinate on the object.
CLLocationCoordinate2D coord = [[currentDisplayedTowers lastObject] coordinate];

As SB said, make sure your array is allocated and initialized.
You’ll also probably want to use NSValue wrapping as in your second code snippet. Then decoding is as simple as:
NSValue *wrappedCoordinates = [currentlyDisplayedTowers lastObject]; // or whatever object you wish to grab
CLLocationCoordinate2D coordinates;
[wrappedCoordinates getValue:&coordinates];

You need to allocate your array.
NSMutableArray* currentlyDisplayedTowers = [[NSMutableArray alloc] init];
Then you can use it. Be sure to call release when you are done with it or use another factory method.

I had currentlyDisplayedTowers = nil which was causing all the problems. Also, the previous advice to init and alloc were necessary. Thanks everyone for the help!

For anyone else with this issue, there's another solution if you are planning on using MapKit.
(The reason I say IF, of course, is because importing a module such as MapKit purely for a convenient wrapper method is probably not the best move.. but nonetheless here you go.)
#import MapKit;
Then just use MapKit's coordinate value wrapper whenever you need to:
[coordinateArray addObject:[NSValue valueWithMKCoordinate:coordinateToAdd]];
In your example..
[currentlyDisplayedTowers addObject:[NSValue valueWithMKCoordinate:new_coordinate]];

Related

Get variable or object from IBAction method

I have been reading, googling and watching Lynda videos to find the answer for this the last couple days. I haven't found a good answer yet.
This seems like it should be pretty simple. With normal methods I can pass variables. But with IBAction being (void) I cant figure out how to get a variable to another method.
Here are some simple examples of what I would like to do:
- (IBAction)treeButton:(id)sender {
int test = 10;
}
-(void)myMethod{
NSLog(#"the value of test is %i",test);
}
This what I really want to have work. I am try to have a button set the initial location that I want to store and use in another method.
- (IBAction)locationButton:(id)sender {
CLLocation *loc1 = [[CLLocation alloc]
initWithLatitude:_locationManager.location.coordinate.latitude
longitude:_locationManager.location.coordinate.longitude];
}
-(void)myMethod{
NSLog(#"the value of test is %i",test);
NSLog(#"location 1 is %#",loc1);
}
Any suggestions to lead me in the right direction would be great. I have read and watched videos on variable scope, instance varaibles etc. Just not understanding what I need to do here
Change myMethod to accept the parameters you need:
- (void)myMethod:(CLLocation *)location {
NSLog(#"location 1 is %#", location);
}
Invoke it something like so:
- (IBAction)locationButton:(id)sender {
CLLocation *loc1 = [[CLLocation alloc]
initWithLatitude:_locationManager.location.coordinate.latitude
longitude:_locationManager.location.coordinate.longitude];
[self myMethod:loc1];
}
If you need it to be accessible by multiple methods or at different points in the code, I recommend creating an instance variable for loc1 in your #interface declaration.
#interface MyClass : NSObject {
CLLocation *loc1;
}
In your method, instead of re-declaring it, you'd just set it:
loc1 = [[CLLocation alloc]
initWithLatitude:_locationManager.location.coordinate.latitude
longitude:_locationManager.location.coordinate.longitude];
In myMethod, just access it:
- (void)myMethod{
NSLog(#"location 1 is %#", loc1);
}

Override the NSObject data

i have one array this array contain Question Objects so here i need to change the positions for array
Question *que=[[Question alloc]init];
que=[myarray objectAtIndex:1];
Question *que1=[[Question alloc]init];
que1=[myarray objectAtIndex:2];
here i need to inter change objects each other some
[que1 setValue: que.name forKey:#"Name"];
[myarray relplaceObjectAtIndex:2 withObject:que1];
is it right way to set value same objectValues
Please guide me hoe can inter change value.
Thanks for advance
There are significant issues with your code here:
This statement:
Question *que = [[Question alloc] init];
Allocates a new Question instance and assigns it to the variable que. When you do:
que = [myarray objectAtIndex:1];
You are overwriting the Question instance that you just allocated, effectively leaking memory (because you never released it). This won't be a problem if you are using ARC but nevertheless it is something to be mindful of because with or without ARC it is pointless. You did this twice, once for que and once for que1. Since you don't actually need to allocate and initialise a new Question instance, you can just do:
Question *que = [myarray objectAtIndex:1];
You obtain a reference to a Question object and assign it to que1. Then you mutate it and want to put it back into the array. This is pointless because the array already holds a reference to the same Question instance that you obtained with objectAtIndex:.
You haven't really explained what you are trying to do. Your entire code basically boils down to:
[[[myarray objectAtIndex:2] setValue:[[myarray objectAtIndex:1] name] forKey:#"Name"];
Your code should work how you intend with what you have shown. Just a few points to be aware of:
You need myarray to be an NSMutableArray
You have a typo here: relplaceObjectAtIndex:2 it should be replaceObjectAtIndex
Arrays start at index 0, which I'm sure you are aware of.
First use NSMutableArray object to hold it not NSArray
then.
you need to understand one main thing you are holding only a pointer to an object. array is managing it. You have created an object before accessing object inside array, dont do that it creates memory leak. You have to access the object from array only.
Question * que1=[myarray objectAtIndex:1];
[que1 retain];
[myarray removeObjectAtIndex:1];
Question * que2=[myarray objectAtIndex:2];
[que2 retain];
[myarray removeObjectAtIndex:2];
its possible you are not using ARC and your array is the only owner of the object. So If you remove object from array the it might release the whole object
[myarray insertObject:que2 atIndex:1];
[myarray insertObject:que1 atIndex:2];
this is a sample to put object in any position.
Read class references NSMutableArray

NSMutableArray retain count

target_locations[ 0] = [[CLLocation alloc] initWithLatitude : 51.50373056
longitude : 0.129986111];
[target_locations[ 0] release];
Consider the above code, is it the proper way to keep the assigned object to have a retain count of 1 ?
*Assuming ARC is not activated.
Given that target_locations is an NSMutableArray, and that ARC is not enabled, the correct procedure here is as follows:
CLLocation * newLocation = [[CLLocation alloc] initWithLatitude : 51.50373056
longitude : 0.129986111];
target_locations[0] = newLocation;
[newLocation release];
You shouldn't send release to the result of an array access because you don't own that object through that pointer. While it does work in this case, it's incorrect semantically and too likely to cause problems if you get into the habit.
Also, consider renaming target_locations to targetLocations, which is consistent with Cocoa style. Using the underscore makes it look like a plain-C array rather than an object.

read latitude and longitude from sqlite iphone

I have been struggling with this for long. I read many resources but still not able to find a clear way around it.
I have a Sqlite table with rows of latitudes and longitudes. My task is to fetch those latitudes and longitudes and put them in an array and then use later for displaying on map with all the pins. I do these "reading from database" in my AppDelegate (is this advisable or is it better to do in view controller which has the map?)
I fetch the lat and long as double values as shown below
while (sqlite3_step(selectStmt)==SQLITE_ROW){
double latitude= sqlite3_column_double(selectStmt, 1);
double longitude= sqlite3_column_double(selectStmt, 2);
CLLocationCoordinate2D coord=CLLocationCoordinate2DMake(latitude,longitude);
// I want to add this to an array, so that i can use later for annotations
}
However when i try to add "Incompatible type for argument 1 off addObject".
Is this the right way of fetching multiple coordinates from sqlite to display on maps?
Help would be appreciated
You need to use CLLocation class to store your location data.
http://developer.apple.com/library/ios/#DOCUMENTATION/CoreLocation/Reference/CLLocation_Class/CLLocation/CLLocation.html#//apple_ref/doc/uid/TP40007126
CLLocation *location = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
[array addObject:location];
[location release];
CLLocationCoordinate2D is a struct not an object and you need objects for addObject methods.
You can use the CLLocation as Evgeniy suggest or create your own object to store/retrieve those values.

Iphone application. Crash without the self keyword

I will try to make myself as clear as possible. Let start from the beginning. I have an application with a tableview that contains a list of places with distances from myLocation. Now everytime I get an update in the gps location I run the following code
- (void)locationUpdate:(CLLocation *)location {
myLocation = location;
for (Trek * trek in list) {
CLLocation *loc = [[CLLocation alloc] initWithLatitude:[trek latitude_start] longitude:[trek longitude_start]];
double dis = [locationManager getDistance: loc];
[trek setDistance:dis];
[trek setDistanceUnit];
[loc release];
}
[self.tableView reloadData];
}
Now this piece of code [trek setDistanceUnit]; calls
-(void) setDistanceUnit {
if (self.distance < 1000.0)
self.distanceString = [NSString stringWithFormat:#"%.0lf m", self.distance];
}
Now if I use only distanceString the application crash. Now I think it may have something to do with the fact that those updates may run concurrently (in parallel) to the access required by the view to draw the cells. Anyone has any idea? I can post more code if helpful, I just didn't want to post too much to make this post too long.
I tried to search everywhere but I could not found anything so far.
Thanks in advance,
Umberto
PS Now the application is working but I would like to understand what is going on.
If your distanceString is a retain property, assigning it without self sets it up for a crash because you bypass the setter, and assign the string without retaining it. So when the string gets deallocated on being sent to the autorelease pool, your app crashes.
By synthesizing the accessors using #synthesize and using the dot notation (or setDistanceString:), the object will retain the string for you so that it always has a pointer to it for itself (until it's released).