views:

17278

answers:

6

I'm having troubles creating a property of an array of integers in Objective C. I'm not sure whether this is even possible to do in Obj-C so I'm hoping someone can help me in finding out either how to do it correctly or provide an alternative solution.

myclass.h

@interface myClass : NSObject {

@private int doubleDigits[10];
}

@property int doubleDigits;
@end

myclass.m

@implementation myClass

    @synthesize doubleDigits;
    -(id) init {

        self = [super init];

        int doubleDigits[10] = {1,2,3,4,5,6,7,8,9,10};

        return self;
    }

    @end

When I build and run, I get the following error:

error: type of property 'doubleDigits' does not match type of ivar 'doubleDigits'

Hopefully someone can either provide a solution or steer me in the correct direction.

Thanks in advance.

+2  A: 

I'm just speculating:

I think that the variable defined in the ivars allocates the space right in the object. This prevents you from creating accessors because you can't give an array by value to a function but only through a pointer. Therefore you have to use a pointer in the ivars:

int *doubleDigits;

And then allocate the space for it in the init-method:

@synthesize doubleDigits;

- (id)init {
    if (self = [super init]) {
        doubleDigits = malloc(sizeof(int) * 10);
        /*
         * This works, but is dangerous (forbidden) because bufferDoubleDigits
         * gets deleted at the end of -(id)init because it's on the stack:
         * int bufferDoubleDigits[] = {1,2,3,4,5,6,7,8,9,10};
         * [self setDoubleDigits:bufferDoubleDigits];
         *
         * If you want to be on the safe side use memcpy() (needs #include <string.h>)
         * doubleDigits = malloc(sizeof(int) * 10);
         * int bufferDoubleDigits[] = {1,2,3,4,5,6,7,8,9,10};
         * memcpy(doubleDigits, bufferDoubleDigits, sizeof(int) * 10);
         */
    }
    return self;
}

- (void)dealloc {
    free(doubleDigits);
    [super dealloc];
}

In this case the interface looks like this:

@interface MyClass : NSObject {
    int *doubleDigits;
}
@property int *doubleDigits;

Edit:

I'm really unsure wether it's allowed to do this, are those values really on the stack or are they stored somewhere else? They are probably stored on the stack and therefore not safe to use in this context. (See the question on initializer lists)

int bufferDoubleDigits[] = {1,2,3,4,5,6,7,8,9,10};
[self setDoubleDigits:bufferDoubleDigits];
Georg
This didn't yield different results. Any other ideas?
woopstash
I really hope it's correct this time.
Georg
+2  A: 
error: type of property 'doubleDigits' does not match type of ivar 'doubleDigits'

because

int doubleDigits[10] <= array

int doubleDigits <= single integer

Igor
+3  A: 

This should work:

@interface MyClass
{
    int _doubleDigits[10]; 
}

@property(readonly) int *doubleDigits;

@end

@implementation MyClass

- (int *)doubleDigits
{
    return _doubleDigits;
}

@end
robottobor
+1  A: 

This works

@interface RGBComponents : NSObject {

float components[8];

}

@property(readonly) float * components;


  • (float *) components { return components; }
Martin West
+6  A: 

C arrays are not one of the supported data types for properties. See "The Objective-C Programming Language" in Xcode documentation, in the Declared Properties page:

Supported Types

You can declare a property for any Objective-C class, Core Foundation data type, or “plain old data” (POD) type (see C++ Language Note: POD Types). For constraints on using Core Foundation types, however, see “Core Foundation.”

POD does not include C arrays. See http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html

If you need an array, you should use NSArray or NSData.

The workarounds, as I see it, are like using (void *) to circumvent type checking. You can do it, but it makes your code less maintainable.

lucius
A: 

to everyone who is saying to use nsarrays i would like to know how you can optimize for cache hits using nsarray. you can allocate it with a specific number of elements, but after you surpass your initial array size, each new element could be scattered all over memory depending on implementation of said NSArray. plus you dont want to hog your ram with empty array elements. i would prefer a linked list-array hybrid that points to contiguous blocks of memory allocated to a size no bigger than 1/8'th the cpu's L1 cache, with a variable block size option so you can fine tune for efficiency. using a generic data structure may be the easiest solution but theres probably a better way. ps. im speaking only for games or apps that have many objects being accessed and modified.

mike
@Mike: Welcome to SO. This isn't a discussion forum, so please don't leave new "answers" to questions that are just commentary-- there's a comment function on the original question as well as on each answer.
quixoto