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

时间:2023-01-15 14:49:35

thing.h

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

@property float stuff;
@end

thing.m

@implementation Thing
@synthesize stuff;
@end

I get error: type of property 'stuff' does not match type of ivar 'stuff'

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

I don't want to use an NSArray because I'd have to make the floats into NSNumbers (right?) and that's a pain to do math with.

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

Update: I've noticed similar answers had guesses and trial answers. While I appreciate the attempts by non-Objective-C folks, I'm hoping for a definitive answer whether it's possible or not.

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

6 个解决方案

#1


OK, I have compiled up the following code at it works as expected.

好的,我编译了以下代码,它按预期工作。

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

then in your other application code you can do something like the following:

然后在您的其他应用程序代码中,您可以执行以下操作:

** FloatTestCode.h **

** FloatTestCode.h **

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

@interface FloatTestCode : NSObject {
    FloatHolder* holder;
}

- (void) doIt:(id)sender;

@end

** FloatTestCode.m **

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

#2


The type of the property must match the type of the instance variable it will be stored in, so you could do something like

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

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

  @property float[30] stuff;
  @end

and it should work. I wouldn't recommend it though. I'm guessing you're looking for something like indexed properties from Delphi. The closest you'll get is something like the following.

它应该工作。我不会推荐它。我猜你正在寻找像Delphi的索引属性这样的东西。你得到的最接近的是如下。

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

  - (void) setStuff:(float)value atIndex:(int)index;
  - (float) getStuffAtIndex:(int)index;
  @end

#3


You can't do it the way you want to do it. You can jump through some hoops and get something similar, e.g. using Daniel's solution, but it's not quite the same thing. The reason you can't do it is that arrays are not lvalues in C. An lvalue is something that can appear on the left-hand side of an assignment. The following code is invalid C:

你不能按照你想要的方式去做。你可以跳过一些箍,得到类似的东西,例如:使用丹尼尔的解决方案,但它不是一回事。你不能这样做的原因是数组不是C中的左值。左值可以出现在赋值的左侧。以下代码无效C:

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

As a consequence, you can't declare properties whose types are not lvalues.

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

#4


Daniel's FloatHolder answer has a major bug (edit: he's now fixed it). It only allocates memory for one float and not for the whole array.

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

The line:

_values = malloc(sizeof(float));

_values = malloc(sizeof(float));

Should be:

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

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

Otherwise it seems to be a good answer. Sorry couldn't work out how to reply directly. (edit: I didn't have the necessary privilege on * then.)

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

#5


Even if you could get that to compile, it wouldn't behave well. 'stuff' would return a float*, and the client would have no idea how long the array way; 'setStuff:' would just change the pointer, and you'd either be pointing to stack-allocated data that would vanish out from under you or heap-allocated data that would leak because it wouldn't know to free it.

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

#6


I'm not well-versed in Objective-C 2.0, but I'm guessing that the issue might be caused by the fact that a C array is essentially just a pointer to the first element of the array, meaning that the type of float stuff[30] is actually float *, not merely a float.

我不是很熟悉Objective-C 2.0,但我猜这个问题可能是因为C数组本质上只是指向数组第一个元素的指针,这意味着浮点数的类型东西[30]实际上是漂浮物*,而不仅仅是浮子。

#1


OK, I have compiled up the following code at it works as expected.

好的,我编译了以下代码,它按预期工作。

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

then in your other application code you can do something like the following:

然后在您的其他应用程序代码中,您可以执行以下操作:

** FloatTestCode.h **

** FloatTestCode.h **

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

@interface FloatTestCode : NSObject {
    FloatHolder* holder;
}

- (void) doIt:(id)sender;

@end

** FloatTestCode.m **

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

#2


The type of the property must match the type of the instance variable it will be stored in, so you could do something like

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

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

  @property float[30] stuff;
  @end

and it should work. I wouldn't recommend it though. I'm guessing you're looking for something like indexed properties from Delphi. The closest you'll get is something like the following.

它应该工作。我不会推荐它。我猜你正在寻找像Delphi的索引属性这样的东西。你得到的最接近的是如下。

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

  - (void) setStuff:(float)value atIndex:(int)index;
  - (float) getStuffAtIndex:(int)index;
  @end

#3


You can't do it the way you want to do it. You can jump through some hoops and get something similar, e.g. using Daniel's solution, but it's not quite the same thing. The reason you can't do it is that arrays are not lvalues in C. An lvalue is something that can appear on the left-hand side of an assignment. The following code is invalid C:

你不能按照你想要的方式去做。你可以跳过一些箍,得到类似的东西,例如:使用丹尼尔的解决方案,但它不是一回事。你不能这样做的原因是数组不是C中的左值。左值可以出现在赋值的左侧。以下代码无效C:

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

As a consequence, you can't declare properties whose types are not lvalues.

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

#4


Daniel's FloatHolder answer has a major bug (edit: he's now fixed it). It only allocates memory for one float and not for the whole array.

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

The line:

_values = malloc(sizeof(float));

_values = malloc(sizeof(float));

Should be:

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

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

Otherwise it seems to be a good answer. Sorry couldn't work out how to reply directly. (edit: I didn't have the necessary privilege on * then.)

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

#5


Even if you could get that to compile, it wouldn't behave well. 'stuff' would return a float*, and the client would have no idea how long the array way; 'setStuff:' would just change the pointer, and you'd either be pointing to stack-allocated data that would vanish out from under you or heap-allocated data that would leak because it wouldn't know to free it.

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

#6


I'm not well-versed in Objective-C 2.0, but I'm guessing that the issue might be caused by the fact that a C array is essentially just a pointer to the first element of the array, meaning that the type of float stuff[30] is actually float *, not merely a float.

我不是很熟悉Objective-C 2.0,但我猜这个问题可能是因为C数组本质上只是指向数组第一个元素的指针,这意味着浮点数的类型东西[30]实际上是漂浮物*,而不仅仅是浮子。