My map object has a set of coordinates. It doesn't always have the same number of coordinates.
In java I'd just declare the object as Double[] xpoints and would set it's size when instantiating a map like this: xpoints = new double[npoints];
How can I do this with objective-c?
I tried doing this: @property(nonatomic) double * xpoints; but somehow all of it's values turn to 0 when I print it with NSLog.
Map's init:
-(id)initWithXpoints:(double[]) xpointss Ypoints:(double[]) ypointss Npoints:(int)npointss
{
self = [super init];
if (self)
{
self.xpoints = xpointss;
self.ypoints = ypointss;
self.npoints = npointss;
}
return self;
}
Something weird happens though. The values are changed to zero when I print xpoints[0] from the object that created the map. The first time I print it it works. The second time it just prints zero.
I think it happens because xpointss sent to init is removed from the memory. How can I "instantiate" the xpoints property if it's a pointer?
Is there a better way to do this?
added: I tried creating a temporary xpoints like this:
double tempxpoints[npointss];
double tempypoints[npointss];
for (int i = 0; i < npointss; i++)
{
tempxpoints[i] = xpointss[i];
tempypoints[i] = ypointss[i];
}
self.xpoints = tempxpoints;
self.ypoints = tempypoints;
But it still didn't work.
Edit: Thanks for all the answers. This ended up being my final Init code:
-(id)initWithXpoints:(double[]) xpointss Ypoints:(double[]) ypointss Npoints:(int)npointss
{
self = [super init];
if (self)
{
_xpoints = [[NSMutableArray alloc] init];
_ypoints = [[NSMutableArray alloc] init];
for (int i = 0; i < npointss; i++)
{
NSNumber *tempx = [NSNumber numberWithDouble:xpointss[i]];
NSNumber *tempy = [NSNumber numberWithDouble:ypointss[i]];
[_xpoints addObject:tempx];
[_ypoints addObject:tempy];
}
_npoints = npointss;
}
return self;
}
If you allocate the arrays as local variables, then they will be allocated on the stack. When execution leaves the function, those memory areas are freed up. You must use malloc() to allocate arrays that you can pass around and use free() to free them up.
// to allocate
double[] tempxpoints = (double[])malloc(sizeof(double) * npointss);
// to free when not used any more
free(tempxpoints);
But actually NSArray has been designed to handle these cases. And with ARC you don't even have to care about freeing the memory.
NSMutableArray *tempxpoints = [[NSMutableArray alloc] init];
[tempxpoints addObject:@2]; // wrap the double in an NSNumber object
If you were being fully Objective-C about it, you'd use an NSArray, fill it with NSNumbers and never specify a length. You can usually give them hints about how much space is likely to be required but Objective-C's collections all always size dynamically.
As of recent versions of the compiler, you can use array[x] notation on NSArray and write direct NSNumber constants as e.g. @4.5f if that sweetens the deal at all.
If you literally want C-style arrays then you'll need to descend to the C level of thought. So, something like:
@property(nonatomic, readonly) double * xpoints;
And:
-(id)initWithXpoints:(double[]) xpointss Ypoints:(double[]) ypointss Npoints:(int)npointss
{
self = [super init];
if (self){
size_t sizeOfArraysInBytes = sizeof(double)*npointss;
_xpoints = (double *)malloc(sizeOfArraysInBytes);
memcpy(_xpoints, xpointss, sizeOfArraysInBytes);
/* ... etc ... */
/* you never use self. notation in an init because it's a method call,
and method calls on objects that are not yet fully instantiated aren't
safe. Sample cause of failure: a subclass overrides the setter */
}
return self;
}
- (void)dealloc
{
free(_xpoints);
/* ... etc ... */
}
The array itself will be read/write elsewhere (it's the pointer that's read-only, not the things it points to) as class.xpoints[0], etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With