Создайте массив целочисленных свойств в Objective-C

У меня проблемы с созданием свойства массива целых чисел в Objective-C. Я не уверен, возможно ли это сделать в Obj-C, поэтому я надеюсь, что кто-то может помочь мне узнать, как это сделать правильно, или предоставить альтернативное решение.

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

Когда я собираю и запускаю, я получаю следующую ошибку:

ошибка: тип свойства doubleDigits не соответствует типу ivar doubleDigits


person jebcrum    schedule 24.01.2009    source источник
comment
Есть ли какая-то конкретная причина, по которой вы хотите использовать примитивные массивы вместо NSArray? Вы должны быть осторожны, чтобы не переопределить классы стандартной структуры данных, если они не работают для вас.   -  person user57368    schedule 25.01.2009
comment
@end (в myclass.h) точка с запятой не нужна. Также вы должны начинать имена классов с заглавной буквы.   -  person Georg Schölly    schedule 25.01.2009
comment
@unknown (google), причина в том, что я просто изучил его, но не смог ничего построить даже близко. Я пробовал NSArray NSNumbers, но не мог понять. @gs: извините, это была еще одна опечатка, которую я исправил. Кроме того, я согласен с названием класса; на самом деле это фракция в реальном коде.   -  person jebcrum    schedule 25.01.2009


Ответы (7)


Это должно работать:

@interface MyClass
{
    int _doubleDigits[10]; 
}

@property(readonly) int *doubleDigits;

@end

@implementation MyClass

- (int *)doubleDigits
{
    return _doubleDigits;
}

@end
person robottobor    schedule 25.01.2009
comment
Чтобы добавить к этому, можно также назначить переменной. В этом случае используйте @property(assign) и: -(void)setDoubleDigits:(int*)doubleDigits { memcpy(_doubleDigits, doubleDigits, 10*sizeof(int)); } - person Ivan Vučica; 09.03.2011
comment
sizeof(_doubleDigits), а не 10 * sizeof(int), пожалуйста. :( - person ; 21.07.2012
comment
Извините, но это просто не работает, вы не можете объявить переменную типа int в @interface. - person Kevin; 10.03.2017

Массивы C не являются одним из поддерживаемых типов данных для свойств. См. «Язык программирования Objective-C» в документации Xcode на странице Объявленных свойств:

Поддерживаемые типы

Вы можете объявить свойство для любого класса Objective-C, типа данных Core Foundation или типа «простые старые данные» (POD) (см. Примечание по языку C ++: Типы POD). Однако для получения информации об ограничениях на использование типов Core Foundation см. «Core Foundation».

POD не включает массивы C. См. http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html

Если вам нужен массив, вы должны использовать NSArray или NSData.

На мой взгляд, обходные пути похожи на использование (void *) для обхода проверки типов. Вы можете это сделать, но это сделает ваш код менее удобным в обслуживании.

person lucius    schedule 30.12.2009
comment
Цитата из вашей ссылки: Термин «типы POD» в совокупности относится к следующим категориям типов C ++ и охватывает как их версии с квалификацией cv, так и их массивы [§3.9, 10; §9, §4]: скалярные типы, [...]. - person Ivan Vučica; 09.03.2011

Как сказал Люциус, невозможно иметь свойство массива C. Использование NSArray - лучший способ. В массиве хранятся только объекты, поэтому вам придется использовать NSNumbers для хранения ваших int. Благодаря новому синтаксису литерала инициализация очень проста и понятна:

NSArray *doubleDigits = @[ @1, @2, @3, @4, @5, @6, @7, @8, @9, @10 ];

Or:

NSMutableArray *doubleDigits = [NSMutableArray array];

for (int n = 1; n <= 10; n++)
    [doubleDigits addObject:@(n)];

Для получения дополнительной информации: Справочник по классу NSArray, Справочник по классу NSNumber, Литеральный синтаксис

person Tim Vermeulen    schedule 12.10.2012
comment
Откуда вы знаете, что это невозможно? - person Gabe; 12.10.2012

Я просто размышляю:

Я думаю, что переменная, определенная в ivars, выделяет пространство прямо в объекте. Это предотвращает создание средств доступа, поскольку вы не можете передать массив по значению функции, а только через указатель. Поэтому вам нужно использовать указатель в ivars:

int *doubleDigits;

А затем выделите для него место в init-методе:

@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];
}

В этом случае интерфейс выглядит так:

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

Изменить:

Я действительно не уверен, разрешено ли это делать, действительно ли эти значения находятся в стеке или они хранятся где-то еще? Они, вероятно, хранятся в стеке и поэтому небезопасны для использования в этом контексте. (См. вопрос о списках инициализаторов)

int bufferDoubleDigits[] = {1,2,3,4,5,6,7,8,9,10};
[self setDoubleDigits:bufferDoubleDigits];
person Community    schedule 24.01.2009
comment
Других результатов это не дало. Есть другие идеи? - person jebcrum; 25.01.2009

Это работает

@interface RGBComponents : NSObject {

    float components[8];

}

@property(readonly) float * components;

- (float *) components {
    return components;
}
person Martin West    schedule 29.12.2009
comment
Это правильный способ сделать? или это не естественный путь в объективе c? - person user1280535; 31.08.2012
comment
Только чтение? Я думаю, что OP тоже хочет иметь автоматические установщики. - person quantumpotato; 14.09.2012
comment
@quantumpotato Это только для чтения, потому что вы не хотите изменять свойство, чтобы оно указывало на что-то еще. Однако вы все равно можете изменить элементы массива. - person bugloaf; 17.07.2014

Вы можете поместить это в свой .h файл для своего класса и определить его как свойство в XCode 7:

@property int  (*stuffILike) [10];
person Vladimir Despotovic    schedule 07.04.2016

Я нашел все предыдущие ответы слишком сложными. Мне нужно было сохранить массив некоторых int как свойство, и я обнаружил, что требование ObjC об использовании NSArray является ненужным усложнением моего программного обеспечения.

Итак, я использовал это:

typedef struct my10ints {
    int arr[10];
} my10ints;

@interface myClasss : NSObject

@property my10ints doubleDigits;

@end

Это компилируется чисто с использованием Xcode 6.2.

Мое намерение было использовать его так:

myClass obj;
obj.doubleDigits.arr[0] = 4;

ОДНАКО это не работает. Вот что он производит:

int i = 4;
myClass obj;
obj.doubleDigits.arr[0] = i;
i = obj.doubleDigits.arr[0];
// i is now 0 !!!

Единственный способ использовать это правильно:

int i = 4;
myClass obj;
my10ints ints;
ints = obj.doubleDigits;
ints.arr[0] = i;
obj.doubleDigits = ints;
i = obj.doubleDigits.arr[0];
// i is now 4

и поэтому полностью опровергает мою точку зрения (избегая сложности использования NSArray).

person gog    schedule 02.03.2016