2

I want to have an internal int array for my class, but I can't seem to get XCode to let me. The array size needs to be set on initialization so I can't put the size directly into the interface.

At the moment I've been trying:

@interface TestClass : NSObject {
  int test[];
}

But it tells me that I'm not allowed. How to I refer to it in my interface, and then how do I allocate it when I create the implementation?

Sorry for a somewhat standard sounding question, but I can't seem to find the answer I need from searching.

edit: I want to use an array because it's apparently much faster than using an NSArray

5
  • 1
    Declare it outside of @interface or use NSArray. Commented Aug 12, 2013 at 9:23
  • 2
    Use NSNumber to treat numbers as objects. Commented Aug 12, 2013 at 9:29
  • 1
    I'm trying to move my implementation away from NSArray at the moment. If it's something every class should have then it should be in the interface shouldn't it? I'm not too sure. Commented Aug 12, 2013 at 9:31
  • 1
    Any particular reason why you don't want to use NSArray? Commented Aug 12, 2013 at 9:34
  • " I want to use an array because it's apparently much faster than using an NSArray" ... Honestly, the difference would be so imperceptible that it's not worth the hassle. Commented May 19, 2015 at 8:37

3 Answers 3

2

You can use a number of methods to overcome this problem, but the easiest is to simply make the instance variable a pointer, like this:

@interface TestClass : NSObject {
    int *test;
}

@property int *test;

@end

Synthesizing the property will give it getter and setter methods which you can use to set its contents:

@implementation TestClass
@synthesize test;

//contents of class

@end

You can then use it like this:

TestClass *pointerTest = [[TestClass alloc] init];

int *array = (int *)malloc(sizeof(int) * count);
//set values

[pointerTest setTest:array];
[pointerTest doSomething];

However, using objects like NSNumber in an NSArray is a better way to go, perhaps you could do something like this:

@interface TestClass : NSObject {
    NSArray *objectArray;
}

@property (nonatomic, strong) NSArray *objectArray;

@end

@implementation TestClass
@synthesize objectArray;

//contents of class

@end

You can then set its contents with a pointer to an NSArray object:

NSArray *items = [NSArray arrayWithObjects:[NSNumber numberWithInt:1], [NSNumber numberWithInt:2], nil];

TestClass *arrayClass = [[TestClass alloc] init];
[arrayClass setItems:items];

[arrayClass doSomething];

When retaining objects upon setting them (like the previous example), always make sure you deallocate the object in the classes dealloc method.

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

3 Comments

Nowadays (with ARC) there's no need to override dealloc to release any objects. This would only be needed for the free of the raw buffer. Yet in your proposed code above the class does not own the buffer. So no dealloc in any case.
It may be easier to use an NSArray, but I was told int array was much faster which is something we are supposed to optimise for in this assignment. Are the gains in speed worth the effort?
"Premature optimization is the root of all evil"
0

A C array is just a sufficiently sized raw memory buffer. Foundation has a nice wrapper around raw memory that frees you from all the manual memory management: NSMutableData

The following approach gives you automatic memory management plus proper encapsulation.

@interface TestClass : NSObject

@property (nonatomic, readonly) int *testArray;
@property (nonatomic, readonly) NSUInteger testArraySize;

@end


@implementation TestClass
{
    NSMutableData *_testData;
}

- (id)initWithSize:(NSUInteger)size
{
    self = [self init];
    if (self != nil) {
        _testData = [NSMutableData dataWithLength:size];
    }
}

- (int *)testArray
{
    return [_testData mutableBytes];
}

- (NSUInteger)testArraySize
{
    return [_testData length];
}

@end

As you see, the ivar does not have to be declared in the @interface.

Comments

-1

Try something like this:

@interface TestClass : NSObject
{
    int *_test; 
}

@property (assign) int *test;

@end

@implementation TestClass

- (instancetype)init
{
    if (self = [super init])
    {
        _test = malloc(sizeof(int) * 20);
    }
    return self;
}

- (int *)test
{
    return _test;
}

- (void)setTest:(int*)test
{
    memcpy(&_test, &test, sizeof(_test));
}

- (void)dealloc
{
    free(_test);
}

@end

4 Comments

"The array size needs to be set on initialization". You use a statically sized array.
@NikolaiRuhe Check my edit. It's only an extra line of magic. I was only showing a guide but I've cleared it up for you.
The problem now is that setTest: does not do what it promises: it does not change test. The property should rather be readonly and the setter something like setTestBytes:length:.
@NikolaiRuhe I did make a typo in setTest: which I have now fixed but other than that, it works perfectly for me.

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.