NSMutableArray seems to be prematurely releasing - iphone

I'm trying to add Annotations to an array to place multiple pins on a map. I have everything in a for loop. The first time it loops through, it adds the object to the array just fine. When it goes back through... the array has 0 objects in it. Can anyone tell me why?
EDIT: I'm using ARC.
-(void)plotMultipleLocs {
float latitude;
float longitude;
NSRange commaIndex;
NSString *coordGroups;
for (int i=0; i<=cgIdArray.count; i++) {
coordGroups = [cgInAreaArray objectAtIndex:i];
commaIndex = [coordGroups rangeOfString:#","];
latitude = [[coordGroups substringToIndex:commaIndex.location] floatValue];
longitude = [[coordGroups substringFromIndex:commaIndex.location + 1] floatValue];
CLLocationCoordinate2D loc = CLLocationCoordinate2DMake(latitude, longitude);
MKCoordinateRegion reg = MKCoordinateRegionMakeWithDistance(loc, 1000, 1000);
self->mapView.region = reg;
MKPointAnnotation* ann = [[MKPointAnnotation alloc] init];
ann.coordinate = loc;
ann.title = [cgNameArray objectAtIndex:i];
ann.subtitle = [cgLocArray objectAtIndex:i];
NSMutableArray *mutAnnArray = [NSMutableArray arrayWithArray:annArray];
[mutAnnArray addObject:ann];
}
}

You are creating a mutable array within the loop and adding your object to it.
At the next iteration of the loop, you create a new mutable array and add a new annotation to it.
Leave aside the fact that you are creating it from another array rather than just adding your annotation to annArray
Basically, the array that you are adding objects to last as long as one iteration, and then goes out of scope.
Try moving the array out of the loop:
-(void)plotMultipleLocs {
float latitude;
float longitude;
NSRange commaIndex;
NSString *coordGroups;
NSMutableArray *mutAnnArray = [NSMutableArray arrayWithArray:annArray]; // Create one array outside the loop.
for (int i=0; i<=cgIdArray.count; i++) {
coordGroups = [cgInAreaArray objectAtIndex:i];
commaIndex = [coordGroups rangeOfString:#","];
latitude = [[coordGroups substringToIndex:commaIndex.location] floatValue];
longitude = [[coordGroups substringFromIndex:commaIndex.location + 1] floatValue];
CLLocationCoordinate2D loc = CLLocationCoordinate2DMake(latitude, longitude);
MKCoordinateRegion reg = MKCoordinateRegionMakeWithDistance(loc, 1000, 1000);
self->mapView.region = reg;
MKPointAnnotation* ann = [[MKPointAnnotation alloc] init];
ann.coordinate = loc;
ann.title = [cgNameArray objectAtIndex:i];
ann.subtitle = [cgLocArray objectAtIndex:i];
[mutAnnArray addObject:ann]; // Add the annotation to the single array.
}
// mutAnnArray will go out of scope here, so maybe return it, or assign it to a property
}

Have you tried retaining the instance to avoid it being released?

Every time through the loop, you create a new mutable array with the contents of a different array. The mutable array containing the object you added on the previous iteration is not kept.

Related

How to create a CLLocationCoordinate2d object

I am trying to to call MKPolylines' + polylineWithCoordinates:count: method.
How can I create a CLLocationCoordinate2D * object in this case. I have gone through this particular answer in CLLocationCoordinate2D without knowing how many will be in the array?
// unpacking an array of NSValues into memory
CLLocationCoordinate2D *points = malloc([mutablePoints count] * sizeof(CLLocationCoordinate2D));
for(int i = 0; i < [mutablePoints count]; i++) {
[[mutablePoints objectAtIndex:i] getValue:(points + i)];
}
MKPolyline *myPolyline = [MKPolyline polylineWithCoordinates:points count:[mutablePoints count]];
free(points);
What kind of entries are in the array mutablePoints in the above case?
If your question is simply what kind of entries are in the array, the answer is quite simple: NSValue entries. You can have a look at this guide for more info on how to use NSValues.
CLLocationCoordinate2D coordinate;
for (int i = 0; i < arr.count; i++)
{
float t1 = [[arr objectAtIndex:1] floatValue];
float t2 = [[arr objectAtIndex:0] floatValue];
coordinate.latitude = t1;
coordinate.longitude = t2;
}

Storing Pointers to a Struct in An Array ? iPhone

I have the below code in my app which mallocs memory to a struct object. This method is called several times in the code, each time mallocing memory for a new Vector3D object.
What I want to do is capture the pointer to the malloced ShapeClass object (a C struct) so that I can later free each object in my dealloc method.
Can anyone advise me how I can add the pointer to an array ?
Thank you.
vectorCount = [floatArray.array count] / 3;
ShapeClass *vectorArray = malloc(sizeof(Vector3D) * vectorCount);
for (int i=0; i<vectorCount; i++) {
vectorArray[i].x = [[floatArray.array objectAtIndex:(i*3)] floatValue];
vectorArray[i].y = [[floatArray.array objectAtIndex:(i*3)+1] floatValue];
vectorArray[i].z = [[floatArray.array objectAtIndex:(i*3)+2] floatValue];
}
return vectorArray;
// I WANT TO INSERT SOMETHING HERE TO CAPTURE THE POINTER TO vectorArray - E.G ADD IT TO AN ARRAY ?
}
}
return NULL;
}
Use [NSValue valueWithPointer:] to store it in the container classes.
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
SomeObject *object = [[SomeObject alloc] init];
//Store the pointer to object
[dictionary setValue:[NSValue valueWithPointer:object] forKey:#"object"];

iOS MKMapView and MKPolyLine

I'm new to iOS programming and am not sure what is wrong with this code:
CLLocationCoordinate2D *locations = malloc(sizeof(CLLocationCoordinate2D) * points.count/2);
int count = 0;
for (int i = 0; i < points.count; i++)
{
CLLocationCoordinate2D point = CLLocationCoordinate2DMake([[points objectAtIndex:i] doubleValue], [[points objectAtIndex:++i] doubleValue]);
// Fill the array.
locations[count] = point;
count++;
NSLog(#"%#", locations[count-1].latitude);
NSLog(#"%#", locations[count-1].longitude);
}
// Create the polyline based on the array of points.
MKPolyline *routeLine = [MKPolyline polylineWithCoordinates:locations count:points.count/2];
MKPolylineView *routeLineView = [[MKPolylineView alloc] initWithPolyline:routeLine];
routeLineView.fillColor = [UIColor blueColor];
routeLineView.strokeColor = [UIColor blueColor];
routeLineView.lineWidth = 5;
// Add overlay to map.
[mapOutlet addOverlay:routeLine];
[mapOutlet setVisibleMapRect:routeLine.boundingMapRect];
// clear the memory allocated earlier for the points.
free(locations);
I get an EXC_BAD_ACCESS error on the first call to NSLOG(). Any thoughts?
FYI: 'points' is an array of strings containing latitude and longitude values.
When you use %# to print a value, NSLog tries to use the argument as an object pointer but these are double float values. Use the %f to print doubles:
NSLog(#"%f", locations[count-1].latitude);
NSLog(#"%f", locations[count-1].longitude);

Adding annotation on Map by parser latitude & longitude values

I have the following code:
MKCoordinateRegion region;
MKCoordinateSpan span;
span.latitudeDelta=0.0005;
span.longitudeDelta=0.0005;
CLLocationCoordinate2D location = mapView.userLocation.coordinate;
for (int i = 0; i < [appDelegate.markers count]; i++) {
marker *aMarker = [appDelegate.markers objectAtIndex:i];
location.latitude = [[aMarker.lat objectAtIndex:i] floatValue];
location.longitude =[[aMarker.lng objectAtIndex:i] floatValue];
region.span=span;
region.center=location;
if(addAnnotation != nil)
{
[mapView removeAnnotation:addAnnotation];
[addAnnotation release];
addAnnotation = nil;
}
addAnnotation = [[AddressAnnotation alloc] initWithCoordinate:location];
[mapView addAnnotation:addAnnotation];
}
I have parsed latitude and longitude in my XMLparser class. Now I want to add annotation on buttonclick event on Map. Can someone correct my code?
The warning NSString may not respond to -objectAtIndex means lat and lng are NSString objects (which don't have an objectAtIndex method).
You don't need to call objectAtIndex on lat and lng--they are the values in the specific marker object you just retrieved from the array.
(By the way, you get the warning when you compile the code--not when you "run" it like in your comment. Secondly, don't ignore compiler warnings. In this case, when you run the code you will get an exception: NSInvalidArgumentException - unrecognized selector.)
The other problem is the loop removes the previously added annotation before adding the current one. If you want to add all the markers to the map, this doesn't make sense. Currently, it would end up adding only the last marker to the map. If you really want to add only the last marker then you don't need to loop through the array (just grab the last marker from the array directly and create an annotation from it).
If instead you do want to add all the markers to the map, the loop should look like this:
for (int i = 0; i < [appDelegate.markers count]; i++)
{
marker *aMarker = [appDelegate.markers objectAtIndex:i];
location.latitude = [aMarker.lat floatValue];
location.longitude =[aMarker.lng floatValue];
AddressAnnotation *addrAnnot = [[AddressAnnotation alloc] initWithCoordinate:location];
[mapView addAnnotation:addrAnnot];
[addrAnnot release];
}
It's not clear what you're doing with region. If you're trying to set the region so that the map view shows all the annotations, look at the answers to this question: iOS MKMapView zoom to show all markers.

CLLocationCoordinate2D without knowing how many will be in the array?

I need to build an array using something like the following:
CLLocationCoordinate2D points[4];
points[0] = CLLocationCoordinate2DMake(41.000512, -109.050116);
points[1] = CLLocationCoordinate2DMake(41.002371, -102.052066);
points[2] = CLLocationCoordinate2DMake(36.993076, -102.041981);
points[3] = CLLocationCoordinate2DMake(36.99892, -109.045267);
Problem is, I will never know how many items are going to be in the array, so I can specify the count. Is there a way to create a CLLocationCoordinate2D array, and just insert new coordinates without knowing what the final total will be?
EDIT: My final goal is to use the coordinates to make an MKPolyline, using the polylineWithCoordinates method which needs a CLLocationCoordinate2D array.
// unpacking an array of NSValues into memory
CLLocationCoordinate2D *points = malloc([mutablePoints count] * sizeof(CLLocationCoordinate2D));
for(int i = 0; i < [mutablePoints count]; i++) {
[[mutablePoints objectAtIndex:i] getValue:(points + i)];
}
MKPolyline *myPolyline = [MKPolyline polylineWithCoordinates:points count:[mutablePoints count]];
free(points);
Box them up in an NSValue object and throw them in an NSMutableArray.