2

In Objective-C, how can I define a C array of 'unknown size' as an instance variable, and later populate the array?

(Background) : I have a class in Objective-C which handles loading game data. The data is stored in an array of C structs, contained in an external datafile. I can load in the array and access it, but I need it to be accessible throughout the class. What I'm trying to do is declare an 'empty' array in my instance variables and then (when loaded) point this empty array or replace it with the one I've loaded in.

This is how I'm loading in my data...

FILE *fptr = NULL;
fptr = fopen([path cStringUsingEncoding:NSUTF8StringEncoding], "r");

// Create an empty array of structs for the input file with known size
frame2d newAnimationData[28];

// Read in array of structs
fread(&newAnimationData, sizeof(newAnimationData), 1, fptr);
fclose(fptr);

So this code works fine to recreate my array of frame2d structs - I just need to know how I can use this as an instance variable.

Any help is appreciated, thanks.

0

3 Answers 3

3

Declare it as frame2d*, then figure out how big it needs to be at runtime and initialize it with calloc(numberOfFrame2Ds, sizeof(frame2d));

Or use an NSMutableArray and wrap the structs in NSValue objects if resizing and safety at runtime is more important than efficiency.

Sign up to request clarification or add additional context in comments.

3 Comments

Note that calloc sets all bits to zero, which is not necessarily what you want for non integral types. It may workd on your machine, but it's not technically correct.
Having calloc zero the memory is a waste when you're immediately going to slurp a file's data in over that freshly zeroed memory. malloc alone would be preferable.
Good points :) I'm always hesitant to recommend malloc over calloc to newbies due to the tendency to get bitten by uninitialized stuff later, but it is appropriate here.
1

Use a pointer to a frame2d object as an instance variable:

frame2D *animationData;

You'll need to allocate the array at runtime using malloc.

If the entire file is nothing but frames, just read it into an NSData object:

// in the interface
@interface MyClass
{
  NSData *animationData;
  frame2D *animationFrames;
}

// in the implementation
animationData = [[NSData alloc] initWithContentsOfFile:path];
animationFrames = (frame2D*) [myData bytes];

-(void) dealloc {
  [animationData release];
}

Comments

1

When you say you need the loaded data to "be accessible throughout the class," it sounds like you will only have a single array that you want all your objects of that class to use. If so, forget the instance variable. You can expose a global frame2d * and have your objects access that:

// Class.h
extern frame2d *gClassFrames;

// Class.m
frame2d *gClassFrames;

/* Somewhere in the class, read in the data and point `gClassFrames` at it.
 * If the array is actually of known size, just declare the entire array rather
 * than a pointer and read the data into that static storage, in order to avoid
 * dynamic memory allocation.*/

Just because you're writing Obj-C doesn't mean you have to throw out everything that works fine in C. Having each object store a pointer to the same array would be a waste of memory.

If you want a more objecty way of getting at the information, you can add a class method to access it, whether it's + (frame2d *)frames or + (frame2d *)frameAtIndex:(NSUInteger)u.

1 Comment

I have an animation class which will produce instances that all have their own animation frames. So each instance should have it's own array of frame2d objects. This is required for management and reuse of animation frames over a number of different entities which I'm animating.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.