【问题标题】:In Objective-C, can I declare @property on a c-array of floats?在 Objective-C 中,我可以在浮点 c 数组上声明 @property 吗?
【发布时间】:2009-05-22 12:37:52
【问题描述】:

东西.h

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

@property float stuff;
@end

东西.m

@implementation Thing
@synthesize stuff;
@end

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

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

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

【问题讨论】:

  • 是的,您必须将它们作为 NSNumbers 插入,因为 NSArray 只接受对象值;但是,您可以通过简单地调用 [number floatValue] 来访问浮点值,其中 number 是您的 NSNumber 对象。
  • 这似乎是要走的路。

标签: objective-c


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

      @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
    

    【讨论】:

    • 您可以简单地将属性设为只读,然后使用普通数组运算符在特定索引处读取和设置值。但我更喜欢你的,因为它更加封装。
    • 编译失败,语法错误。它对你有用吗?
    【解决方案3】:

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

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

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

    【讨论】:

      【解决方案4】:

      丹尼尔的 FloatHolder 答案有一个重大错误(编辑:他现在已修复它)。它只为一个浮点数分配内存,而不是为整个数组分配内存。

      行:

      _values = malloc(sizeof(float));

      应该是:

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

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

      【讨论】:

        【解决方案5】:

        即使您可以编译它,它也不会表现良好。 'stuff' 会返回一个浮点数*,而客户端将不知道数组的长度; 'setStuff:' 只会改变指针,你要么指向堆栈分配的数据,这些数据会从你下面消失,要么指向堆分配的数据,因为它不知道释放它而泄漏。

        【讨论】:

          【解决方案6】:

          我并不精通 Objective-C 2.0,但我猜这个问题可能是由于 C 数组本质上只是一个指向第一个元素的 指针数组的类型,这意味着float stuff[30] 的类型实际上是float *,而不仅仅是float

          【讨论】:

          • 不,C 数组不是指针,它们是数组。恰好数组隐式衰减为指向其第一个元素的指针,但数组和指针之间仍然存在差异。
          猜你喜欢
          • 1970-01-01
          • 2010-11-10
          • 2012-03-10
          • 1970-01-01
          • 2012-02-11
          • 1970-01-01
          • 2011-11-21
          • 1970-01-01
          • 2013-09-20
          相关资源
          最近更新 更多