В Objective-C я могу объявить @property для c-массива с плавающей точкой? - PullRequest
2 голосов
/ 22 мая 2009

thing.h

@interface Thing : NSObject 
{
     float stuff[30];
}

@property float stuff;
@end

thing.m

@implementation Thing
@synthesize stuff;
@end

Я получаю ошибка: тип свойства 'stuff' не соответствует типу ivar 'stuff'

Я не хочу использовать NSArray, потому что мне пришлось бы делать с плавающей точкой NSNumbers (верно?), И с этим трудно вычислять математику.

Обновление : я заметил, что похожие ответы содержали догадки и пробные ответы. Хотя я ценю попытки не-Objective-C, я надеюсь на окончательный ответ, возможно это или нет.

Ответы [ 6 ]

8 голосов
/ 23 мая 2009

ОК, я скомпилировал следующий код, он работает как положено.

FloatHolder.h

@interface FloatHolder : NSObject {
    int _count;
    float* _values;
}

- (id) initWithCount:(int)count;

// possibly look into this for making access shorter
// http://vgable.com/blog/2009/05/15/concise-nsdictionary-and-nsarray-lookup/
- (float)getValueAtIndex:(int)index;
- (void)setValue:(float)value atIndex:(int)index;

@property(readonly) int count;
@property(readonly) float* values; // allows direct unsafe access to the values

@end

FloatHolder.m

#import "FloatHolder.h"


@implementation FloatHolder

@synthesize count = _count;
@synthesize values = _values;

- (id) initWithCount:(int)count {
    self = [super init];
    if (self != nil) {
        _count = count;
        _values = malloc(sizeof(float)*count);
    }
    return self;
}

- (void) dealloc
{
    free(_values);

    [super dealloc];
}

- (float)getValueAtIndex:(int)index {
    if(index<0 || index>=_count) {
        @throw [NSException exceptionWithName: @"Exception" reason: @"Index out of bounds" userInfo: nil];
    }

    return _values[index];
}

- (void)setValue:(float)value atIndex:(int)index {
    if(index<0 || index>=_count) {
        @throw [NSException exceptionWithName: @"Exception" reason: @"Index out of bounds" userInfo: nil];
    }

    _values[index] = value;
}

@end

тогда в другом коде приложения вы можете сделать что-то вроде следующего:

** FloatTestCode.h **

#import <Cocoa/Cocoa.h>
#import "FloatHolder.h"

@interface FloatTestCode : NSObject {
    FloatHolder* holder;
}

- (void) doIt:(id)sender;

@end

** FloatTestCode.m **

#import "FloatTestCode.h"


@implementation FloatTestCode

- (id) init
{
    self = [super init];
    if (self != nil) {
        holder = [[[FloatHolder alloc] initWithCount: 10] retain];
    }
    return self;
}

- (void) dealloc
{
    [holder release];

    [super dealloc];
}

- (void) doIt:(id)sender {
    holder.values[1] = 10;
}
6 голосов
/ 22 мая 2009

Тип свойства должен соответствовать типу переменной экземпляра, в которой оно будет храниться, чтобы вы могли сделать что-то вроде

  @interface Thing : NSObject 
  {
       float stuff[30];
  }

  @property float[30] stuff;
  @end

и это должно работать. Я не рекомендовал бы это все же. Я предполагаю, что вы ищете что-то вроде индексированных свойств от Delphi. Самое близкое, что вы получите, это что-то вроде следующего.

  @interface Thing : NSObject 
  {
       float stuff[30];
  }

  - (void) setStuff:(float)value atIndex:(int)index;
  - (float) getStuffAtIndex:(int)index;
  @end
2 голосов
/ 10 сентября 2010

Ответ Дэниела FloatHolder содержит серьезную ошибку (правка: теперь он исправил это). Он выделяет память только для одного числа с плавающей запятой, а не для всего массива.

Линия:

_values = malloc(sizeof(float));

Должно быть:

_values = malloc(sizeof(float) * count);

В противном случае это будет хороший ответ. Извините, не могу понять, как ответить прямо. (редактировать: тогда у меня не было необходимых прав на stackoverflow.)

2 голосов
/ 23 мая 2009

Вы не можете сделать это так, как вы хотите. Вы можете прыгать через несколько обручей и получить что-то подобное, например, используя решение Даниэля , но это не совсем то же самое. Причина, по которой вы не можете этого сделать, состоит в том, что массивы не являются значениями в C . Lvalue - это то, что может появляться в левой части задания. Следующий код недействителен C:

float stuff1[30], stuff2[30];
stuff1 = stuff2;  // ERROR: arrays are not lvalues

Как следствие, вы не можете объявлять свойства, типы которых не являются lvalues.

1 голос
/ 22 мая 2009

Даже если бы вы могли заставить это скомпилировать, это не будет вести себя хорошо. 'stuff' вернет float *, и клиент не будет знать, как долго будет работать массив; 'setStuff:' просто изменил бы указатель, и вы либо указали бы на данные, выделенные из стека, которые исчезли бы из-под вас, либо данные, выделенные из кучи, которые могли бы просочиться, потому что он не знал, что их освободить.

0 голосов
/ 22 мая 2009

Я не очень разбираюсь в Objective-C 2.0, но я предполагаю, что проблема может быть вызвана тем фактом, что массив C по сути является просто указателем на первый элемент массив, означающий, что тип float stuff[30] на самом деле float *, а не просто float.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...