在 Cocoa 中使用/存储浮点数组
Posted
技术标签:
【中文标题】在 Cocoa 中使用/存储浮点数组【英文标题】:Using/storing an array of floats in Cocoa 【发布时间】:2011-02-18 19:26:20 【问题描述】:在 c 中,如果我想要一个浮点数组(例如),我只需定义固定大小并分配它,我就可以访问每个元素以进行数学运算。但是,我希望能够让我的数组是可变的,因为它们的大小会不断增长(随着应用程序的运行,数组很容易超过 10000 多个元素),而且 NSMutableArray 的想法听起来很棒。但是,(如果我理解正确的话)它只存储对象,我必须将我的数字包装在 NSNumber 中,然后将它们放入数组中。仅存储浮点数(或双精度数或整数)数组似乎是一个荒谬的开销。
另一方面,我看到 Core Data 有 flout 属性,但我不知道如何以相同的方式访问它( array[index] )。我在这里错过了什么吗?是否应该在固定大小的 c 数组中完成所有繁重的数学运算,有没有使用我没有偶然发现的基础类的方法,或者有没有像访问数组一样访问核心数据对象的方法?
【问题讨论】:
重新标记为“可可”,因为这是一个可可问题 - 即使原始海报是为 iPhone/Cocoa-Touch 开发的。 【参考方案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<double> 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 对象 - 但您最终可能会在附加数据(浮点数)方面做更多的簿记工作。
【讨论】:
以上是关于在 Cocoa 中使用/存储浮点数组的主要内容,如果未能解决你的问题,请参考以下文章