Using CGPoints in an NSArray - cocoa-touch

I have been trying to create an array stating the location of a UIImageView in an app I've been working on. What I am trying to do is by using an array I can store the location of my "player" image by using its x,y and z coordinates. The script I am trying to accomplish would look like
NSArray *location[3];
-(IBAction)startup;{
[location addObject: player.center.x];
[location addObject: player.center.y];
[location addObject: playerheight];
}
So I will be able to access this array to move my "player" on the screen in "3-dimensions", but I don't know how to convert the CGpoint values to NSValues so they can be used in the array, is there a simple way to do this inside of the array?

To convert floating point values to objects, use NSNumber. NSValue has wrappers for geometric types like CGPoint. Either would work for you.
[NSValue valueWithCGPoint:player.center];
[NSNumber numberWithFloat:player.center.x];
[NSNumber numberWithFloat:player.center.y];

To addition for the first answer.
When you'll need to read CGPoint back from your array, you can use something like that:
CGPoint point = [(NSValue *)[pointsArray objectAtIndex:i] CGPointValue];

Also note that there's no addObject method for NSArray (you can't add objects to an NSArray after its been created); you want NSMutableArray.
Instead of:
NSArray *location[3];
you probably want something more like:
NSMutableArray *location = [NSMutableArray arrayWithCapacity:3];

Does it have to be an NSArray? Why not use an array of structs?
typedef struct {
CGPoint location;
CGFloat height;
} PlayerLocation;
PlayerLocation players[3];
players[0].location = player.center;
players[0].height = playerheight;
Or depending on your design it may make more sense to declare an objective-C class that contains the x,y,z coordinates as ivars and store those objects into an NSArray.
#interface PlayerLocation : NSObject {
CGPoint location;
CGFloat height;
}
#end

Related

How to use bridge for CLLocationCoordinate2D

AM trying to add CLLocationCoordinate2D[] to NSMutableArray and send it as parameter. But (__bridge id) is crashing the app. Struct to id conversion is the problem. Could anyone please let me know how to use this please.
CLLocationCoordinate2D coordinates[1000];
coordinates[index] --- all the coordinates added to it in loop.
NSMutableArray *coorArray = [NSMutableArray array];
[coorArray addObject:(__bridge id)(coordinates)]; crashes here
Use:
NSMutableArray *coorArray = [NSMutableArray array];
[coorArray addObject:[NSValue valueWithPointer:coordinates]];
Then when you want to retrieve the array of struct:
CLLocationCoordinate2D coordinates[] = [coorArray objectAtIndex:0].pointerValue;
A C array is not an object, so it can't be bridged.
You should look at +[NSValue valueWithBytes:objCType:] not a (__bridge) cast. Bridge is for other things.
e.g.:
[NSValue value:&coordinate withObjCType:#encode(CLLocationCoordinate2D)];
I guess it's possible to encode whole array too

Most efficient way of changing the value of a CGPoint in a CGPoint array?

I have constructed a CG Point array as follows:
NSMutableArray *_startPositions = [NSMutableArray array];
[_startPositions addObject:[NSValue valueWithCGPoint:CGPointMake(0.0, 0.0)]];
[_startPositions addObject:[NSValue valueWithCGPoint:CGPointMake(0.0, 0.0)]];
How can i most efficiently change the x and y values of the points in the array?
If I retrieve the value using:
CGPoint myPoint0 = [[_startPositions objectAtIndex:0] CGPointValue];
I get back a copy of the point. How can I change the x and y values of the CGPoints in the array? I could remove the CGPoint at any position and replace it with one with the correct x,y values, but is there a more efficient way?
Use C array instead of NSMutableArray. If required use C++ STL collection classes such as std::vector or other C/C++ collection library. In this way, you can manipulate the array content without any Obj-C method call.
I suggest you create your own class as
.h
#interface MyPoint : NSObject {
CGPoint point;
}
#property (nonatomic,assign) CGPoint point;
#end
.m
#implementation MyPoint
#synthesize point;
#end
Then add your MyPoint Object in your array.
Change it like
MyPoint *myPoint = [_startPositions objectAtIndex:0];
myPoint.point = myPoint0;
From the docs:
NSValue objects are always immutable.
So your only option here is to create a new NSValue to replace the old one when the CGPoint value changes. If you are looking for a more efficient way to store an array of CGPoints, then a C array is the easiest and fastest way to go.
If you are changing just the 'x' or 'y' value of CGPoint point, you can do this:
((CGPoint *)&point)->x += dx;
or
((CGPoint *)&point)->y += dy;

How to build an array from an array of arrays

I am fairly new to iOS development.
I have a viewController that contains a property that is an object of a custom class. We'll call that custom class ClassA. The object of ClassA has a property that is an NSMutableArray of objects of another custom class we'll call ClassB. ClassB has a property that is also an NSMutableArray of objects of type CLLocation.
From inside a method in the viewController I need to create a C array of CLLocationCoordinate2D structs (CLLocationCoordinate2D is a property of CLLocation). Each of these CLLocationCoordinate2D's needs to come from all of the CLLocation objects held by all of the objects in ClassB and ClassA. If I'm understanding what I've wrought, I believe I have a 3-D array.
I'm stuck on exactly how to go about assembling this array of structs. If it were just one array I would do something like this:
NSUInteger numberOfSteps = [objectOfClassX count];
CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++) {
CLLocation *location = [objectOfClassX objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coordinates[index] = coordinate;
}
However I'm struggling with the syntax of getting each object in the first array, then inside that each object in the second array, then inside that the CLLocationCoordinate2D.
Iterate once to get the total count of coordinates, then iterate again to copy them into a newly-allocated array.
NSInteger coordCount = 0, coordIndex = 0;
for(ClassA *a in collectionOfA)
for(ClassB *b in a.collectionOfB)
coordCount += [b.locations count];
CLLocationCoordinate2D coords[coordCount];
for(ClassA *a in collectionOfA)
for(ClassB *b in a.collectionOfB)
for(CLLocation *location in b.locations)
coords[coordIndex++] = location.coordinate;
just have a try : coordinates = [NSMutableArray arrayWithArray: objectOfClassX];

MapView annotations: finding coordinates

I have many MKMapViews, and each of them has an annotation. I am trying to retrieve the coordinates of each in this way:
for (MKMapView *map in MapViewArray)
{
// add textfield contents to array
NSString *latitude = [NSString stringWithFormat:#"%#", map.annotations];
[latitudes addObject: latitude];
}
I was looking for the right code instead of this:
map.annotations
I want to find the latitude here..
How can I do this??
Each map annotation is an object, so you'll have to get the coordinate value from the annotation instead. The annotations are stored in map.annotations, which is an array. If you only have one annotation per map, you can use this:
CLLocationCoordinate2D coordinate = [[map.annotations lastObject] coordinate];
NSString *latitude = [NSString stringWithFormat:#"%.2f", coordinate.latitude];
If you have multiple annotations, you'll obviously have to iterate through each one individually, then get the location data.

Create a re-sizable array of CGPoints in objective-c

I am trying to create a re-sizable array of CGPoints in objective-c. I've have looked into using NSMutableArray however it doesnt seem to allow resizing. Is there something else I can use?
thank you
Use an NSMutableArray, but just box your CGPoint structs in NSValue objects. Example:
CGPoint myPoint = {0,0};
CGPoint anotherPoint = {42, 69};
NSMutableArray * array = [NSMutableArray array];
[array addObject:[NSValue valueWithCGPoint:myPoint]];
[array addObject:[NSValue valueWithCGPoint:anotherPoint]];
CGPoint retrievedPoint = [[array objectAtIndex:0] CGPointValue];
Note that the +valueWithCGPoint: and CGPointValue methods are only available on the iPhone. However if you need this for the Mac, there are similar methods for dealing with NSPoints, and it's trivial to convert a CGPoint to an NSPoint (you can cast or use NSPointFromCGPoint()).
NSMutableArray is for objects. For plain old datatypes, use NSMutableData and good old pointer typecasts. It's a resizable unstructured memory buffer, just what you need for a vector of PODs. As for static type safety, Objective C does not give you any of that anyway.
EDIT:
Creating a mutable data object with an initial size n CGPoint structs:
NSMutableData *Data = [NSMutableData dataWithLength: n*sizeof(CGPoint)];
Placing a CGPoint pt into the buffer at the i-th position:
CGPoint pt;
NSRange r = {i*sizeof(CGPoint), sizeof(CGPoint)};
[Data replaceBytesInRange: r withBytes:&pt];
Retrieving a CGPoint from the i-th position into pt:
CGPoint pt;
NSRange r = {i*sizeof(CGPoint), sizeof(CGPoint)};
[Data getBytes: &pt range:r];
Growing the array by n objects:
[Data increaseLengthBy:n*sizeof(CGPoint)];
Hope that covers it. See the NSMutableData reference, and keep in mind that all NSData methods apply to it.