【问题标题】:Using/storing an array of floats in Cocoa在 Cocoa 中使用/存储浮点数组
【发布时间】:2011-02-18 19:26:20
【问题描述】:

在 c 中,如果我想要一个浮点数组(例如),我只需定义固定大小并分配它,我就可以访问每个元素以进行数学运算。但是,我希望能够让我的数组是可变的,因为它们的大小会不断增长(随着应用程序的运行,数组很容易超过 10000 多个元素),而且 NSMutableArray 的想法听起来很棒。但是,(如果我理解正确的话)它只存储对象,我必须将我的数字包装在 NSNumber 中,然后将它们放入数组中。仅存储浮点数(或双精度数或整数)数组似乎是一个荒谬的开销。

另一方面,我看到 Core Data 有 flout 属性,但我不知道如何以相同的方式访问它( array[index] )。我在这里错过了什么吗?是否应该在固定大小的 c 数组中完成所有繁重的数学运算,有没有使用我没有偶然发现的基础类的方法,或者有没有像访问数组一样访问核心数据对象的方法?

【问题讨论】:

  • 重新标记为“可可”,因为这是一个可可问题 - 即使原始海报是为 iPhone/Cocoa-Touch 开发的。

标签: iphone arrays cocoa cocoa-touch core-data


【解决方案1】:

你没有错过任何东西;对于 c 标量类型的数组,没有正式的 objc 接口。

简单的方法(如westsider所说)是使用std::vector,然后使用CF/NS-Data等机制实现序列化/反序列化。

如果需要,您可以将 std::vector 包装在 objc 接口中:

/* MONDoubleArray.h */

/* by using pimpl, i'm assuming you are not building everything as objc++ */
struct t_MONDoubleArray_data;

@interface MONDoubleArray : NSObject < NSCoding, NSCopying, NSMutableCopying >
{
    t_MONDoubleArray_data* data;
}

- (double)doubleAtIndex;
- (void)setDoubleAtiIndex:(double)index;
- (NSUInteger)count;

/*...*/

@end

/* MONDoubleArray.mm */

struct t_MONDoubleArray_data {
    std::vector<double> array;
};

@implementation MONDoubleBuffer

- (id)init
{
    self = [super init];
    if (0 != self) {
    /* remember your c++ error handling (e.g., handle exceptions here) */
        array = new t_MONDoubleArray_data;
        if (0 == array) {
            [self release];
            return 0;
        }
    }
    return self;
}

/*...more variants...*/

- (void)dealloc
{
    delete array;
    [super dealloc];
}

- (NSData *)dataRepresentationOfDoubleData { /*...*/ }
- (void)setDoubleDataFromDataRepresentation:(NSData *)data { /*...*/ }

/*...*/

@end

那么,你就可以毫不费力地完成 objc 序列化了。

还有一种方法可以将 CF/NS_MutableArray 用于标量,使用指针(或更窄)大小的条目:

@interface MONFloatBuffer : NSObject
{
    NSMutableArray * floats;
}

@end

@implementation MONFloatBuffer

- (id)init
{
    self = [super init];
    if (0 != self) {
        CFAllocatorRef allocator = 0; /* default */
        CFIndex capacity = 0; /* resizable */
        /* you could implement some of this, if you wanted */
        const CFArrayCallBacks callBacks = { 0 /* version */ , 0 /* retain */ , 0 /* release */ , 0 /* copyDescription */ , 0 /* equal */ };
        floats = (NSMutableArray*)CFArrayCreateMutable(allocator, capacity, &callBacks);
        // now we can read/write pointer sized values to `floats`,
        // and the values won't be passed to CFRetain/CFRelease.
    }
    return self;
}

@end

但是,如果没有自定义,它仍然无法正确反序列化自身。所以... NSPointerArray 可以轻松地完成 more ...但是您仍然固定为指针大小的值,因此您必须自己编写它。这并不难。缺点是您最终可能得到的变体数量。

【讨论】:

  • 谢谢。将它包装在 objc 接口中很好;虽然我失去了 [array index:index] 的简单 array[index] 用法(对我来说看起来很有趣)。我举了第一个例子(修复了几个问题)。它本身就可以很好地遵守(仍然需要添加方法和协议)。但是,如果我添加 MONDoubleArray *doubleArray;到只是一个示例应用程序的应用程序委托接口,然后我在 MONDoubleArray.h 中收到一个错误:“'t_MONDoubleArray_data'之前的预期特定限定符列表”。我整个上午都在寻找合适的解释。有什么想法吗?
  • 好的,将代表从 m 更改为 mm 有效。但是,如果我仍然必须编译将它用作 objc++ 的任何类,那么将它包装在 objc 接口中又有什么意义呢?将我的其他类编译为 objc++ 是否存在任何性能问题?
  • 好吧,您可以将任何方法添加到您想要简化语法的类中。此外,您可以只使用 c++ 并公开向量(假设您要将看到该类的每个翻译切换到 objc++)。至于错误,我为标题发布的代码看起来不错(除了拼写错误'setDoubleAtiIndex')......也许你应该发布你的代码并指出错误发生的行?如果它发生在这里struct t_MONDoubleArray_data { std::vector&lt;double&gt; array; };,那么该部分应该在 MONDoubleArray.mm 中。它是 c++,所以在 c/objc 翻译中编译会失败。
  • @Adam 请参阅上面的帖子,了解构建错误的潜在解决方案。编译 objc++ 的性能问题。程序的运行时性能没有损失。但是,编译时间会更慢,并且需要更多资源。 编译 objc++ 比编译c、objc 或c++ 慢。因为 c++ 的执行速度并不比 c 慢,所以 objc++ 的执行速度并不比 objc 慢。
  • 很高兴了解性能方面。我仍然对为什么必须编译将此类用作 obcj++ 的应用程序委托(在此测试应用程序中)感到困惑?在 t_MONDoubleArray_data* 数组上抛出错误;界面里面。我应该能够使用这个类而无需将其他任何东西编译为 objc++ 吗?只是为了测试一些方法,我尝试添加一个 size 方法,使用 return (int) array.size();它只是用“请求成员'size' in....,它是非类类型't_MONDoubleArray_data *'”而窒息。就在我以为我得到 objc 的时候...谢谢你的帮助
【解决方案2】:

我会避免将您的浮点数包装在 NSNumbers 中并使用 NSMutableArrays。正如你所说,这增加了可笑的开销。

我建议使用 C++ 标准模板库 (STL) 容器。在您的情况下,vector 将是最好的。

使用 STL 将意味着从 Objective-C 迁移到 Objective-C++ ...并且需要将受影响的源文件的扩展名从 .m 更改为 .mm,以及将#import 添加到使用 std 的文件中: :向量。

另一种方法是使用 NSMutableData 对象 - 但您最终可能会在附加数据(浮点数)方面做更多的簿记工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-09
    • 2012-03-13
    • 1970-01-01
    相关资源
    最近更新 更多