为了优化瓶颈,我将大型NSArray的创建转换为c风格的数组。 (由此产生的创作是原始NSArray版本的1/8。是的!)但是一旦它被创建,速度不再是一个问题,所以我宁愿再次受益于它是一个NSArray。
然而,将c风格的数组转换为NSArray似乎非常荒谬(除非我缺少一些神奇的initWithArrayWrapElementsInObjects方法。)
正如我现在理解这个过程,我首先要创建一个NSMutableArray,遍历c样式数组,将每个元素(在我的情况下浮动)转换为对象,将每个对象添加到NSMutableArray,然后创建NSArray与的NSMutableArray。
是吗?必须有更好的方法。
请帮助。
谢谢!
答案 0 :(得分:7)
没有直接的方法来获取你拥有的blob内存并将其廉价地“转换”为NSArray--毕竟,框架需要拥有那个内存,而且它不知道你从哪里得到它from(malloc,stack等)。如果initWithArrayWrapElementsInObjects有一个方便的方法,那么它本身就需要在内部进行你猜测:迭代你提供的内存并向其自身添加项目(可能框架可以像memcpy那样快速地执行此操作,但谁知道)。 / p>
你可以解决这个问题的一种方法(也许是一个有趣的学习练习)是通过实际创建你自己的NSArray子类来完全按照自己的意愿管理内存(即,允许你用你想要的任何语义创建和初始化),但是像NSArray那样对外界起作用。您可以通过继承NSArray并实现方法count:
和objectAtIndex:
来操作您要保留的任何内存。显然,您还需要在init / dealloc等方法中实现对自己内存的管理。查看此页面http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html
在“Subclassing Notes”下。
这里的设计讨论取决于您的数据是什么样的。当然,NSArray期望它的项目是Obj-C引用(类型id
),而不仅仅是任意数据块。如果你的C风格数组持有结构或其他一些非对象引用的原始值,那么这种技术对你来说并不适用 - NSArray的界面永远不会满足于非引用项。
最后一点说明:你提到了一个NSMutableArray并用它“创建”一个NSArray。您应该知道NSMutableArray已经是NSArray,因为它是一个子类。您可以在任何想要NSArray的地方使用NSMutableArray的实例,而无需创建它的新副本。
更新:错过了有关包含浮点数的数组的注释。是的,你有点搞砸了。 NSArrays想要对象。如果容量加倍是昂贵的部分(如另一张海报所述),那么尝试initWithCapacity:。如果它是浮动到对象类型的装箱/拆箱,那么你无能为力。
我已经创建了(但没有方便)一对非常简单的类(称为MYArray和MYMutableArray),这些类旨在用类似NSArray的方法包装这类数据。但它们不能与NSArrays互换。你必须故意使用它们。
更新#2 。我知道这个问题已经存在很久了,但我只是重新审视它并意识到在这个特定情况下实际上有一种巧妙的方法。 (你想从C风格的浮点数组中得到一个不可变的NSArray
)。您可以创建NSArray的自定义子类,它包装浮点值,只有在通过基元访问它们时才将它们转换为对象。这可能会在某些角落出现性能缺陷(?),但它确实可以满足您的要求:
@interface FloatProxyArray : NSArray
{
float * values;
NSUInteger count;
}
- (id)initWithCArray:(float *)arrayOfFloats count:(int)numberOfValues;
@end
@implementation FloatProxyArray
- (id)initWithCArray:(float *)arrayOfFloats count:(int)numberOfValues
{
if ((self = [super init])) {
values = (float *)malloc(numberOfValues * sizeof(float));
if (!values) {
[self release]; return nil;
}
memcpy(values, arrayOfFloats, numberOfValues * sizeof(float));
count = numberOfValues;
}
return self;
}
- (void)dealloc
{
free(values);
[super dealloc]
}
- (NSUInteger)count
{
return count;
}
- (id)objectAtIndex:(NSUInteger)index
{
if (index >= count) {
[NSException raise:NSRangeException format:@""];
return nil;
}
float val = values[index];
return [NSNumber numberWithFloat:val];
}
@end
(N.B。在没有编译/测试的情况下编写在编辑器中。)
答案 1 :(得分:3)
使用NSMutableArray可以进行的一项优化是{{1}},它可以防止数组加倍,这是额外的昂贵操作。
除此之外,由于NSArrays和NSMutableArrays需要对象,因此很难解决这个问题。
答案 2 :(得分:1)
你想获得NSArray的好处是什么?
看起来您可能会更好地使用C数组周围的自定义包装器对象来响应您要调用的任何NSArray消息。否则你回到数组创建的时候......你可以尝试手动创建对initWithObjects的调用,但至少每个浮点数必须包含在NSNumber中,这会再次降低你的速度。
如果你真的需要一个NSArray,因为你想要使用的其他东西需要NSArray对象,那么你可能最好再分类NSArray(遵循Ben发布的指南)。
答案 3 :(得分:0)
“最佳”优化(速度)几乎肯定是为了避免在可能的情况下完全使用NSArray
。