在Objective-C中,我可以在一个浮点数的c数组上声明@property吗?

时间:2009-05-22 12:37:52

标签: objective-c

thing.h

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

@property float stuff;
@end

thing.m

@implementation Thing
@synthesize stuff;
@end

我得到错误:属性'stuff'的类型与ivar'stuff'的类型不匹配

我不想使用NSArray,因为我必须将浮点数转换为NSNumber(对吗?),这对于数学运算很痛苦。

更新:我注意到类似的答案有猜测和试验答案。虽然我很欣赏非Objective-C人员的尝试,但我希望能有一个明确的答案是否可能。

6 个答案:

答案 0 :(得分:8)

好的,我已按预期编译了以下代码。

<强> 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;
}

答案 1 :(得分:6)

属性的类型必须与它将存储的实例变量的类型相匹配,因此您可以执行类似

的操作
  @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 :(得分:2)

你不能按照你想要的方式去做。你可以跳过一些箍,得到类似的东西,例如:使用Daniel's solution,但它并不完全相同。你不能这样做的原因是数组不是C 中的左值。左值可以出现在赋值的左侧。以下代码无效C:

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

因此,您无法声明其类型不是左值的属性。

答案 3 :(得分:2)

Daniel的FloatHolder答案有一个主要的错误(编辑:他现在修复了它)。它只为一个浮点数分配内存,而不是为整个数组分配内存。

该行:

  

_values = malloc(sizeof(float));

应该是:

  

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

否则它似乎是一个很好的答案。抱歉无法解决如何直接回复。 (编辑:那时我在stackoverflow上没有必要的权限。)

答案 4 :(得分:1)

即使你可以编译它,它也不会表现良好。 'stuff'会返回一个浮点*,客户端不知道数组的方式有多长; 'setStuff:'只会改变指针,你要么指向堆栈分配的数据,这些数据会从你或者堆分配的数据中消失掉,因为它不会知道要释放它。

答案 5 :(得分:0)

我不熟悉Objective-C 2.0,但我猜这个问题可能是因为C数组本质上只是第一个元素的指针数组的含义,意味着float stuff[30]的类型实际上是float *,而不仅仅是float