2010-01-03 74 views
5

为了优化瓶颈,我将大型NSArray的创建转换为c样式数组。 (最终创建的是原始NSArray版本的1/8,是的!)但是一旦创建,速度不再是问题,所以我宁愿从它再次成为NSArray中受益。有一个更简单的方法来处理数组!

然而,似乎可笑参与到C风格的数组转换为一个NSArray(除非我失去了一些神奇的initWithArrayWrapElementsInObjects方法。)

正如我现在明白这个过程中,我首先必须创建一个NSMutableArray ,遍历c样式数组,将每个元素转换为对象,将每个对象添加到NSMutableArray中,然后使用NSMutableArray创建NSArray。

是吗?有一个更好的方法。

和帮助,将不胜感激。

谢谢!

回答

7

没有直接的方法来获取你拥有的一块内存,并将其“廉价”转换成一个NSArray--毕竟,框架需要拥有该内存,并且它不知道你拥有的内存它来自(malloc,堆栈等)。如果initWithArrayWrapElementsInObjects有一个简便的方法,它本身需要在内部完成你所推测的内容:遍历你提供的内存并向它自己添加项目(它可能是框架可以像memcpy一样快速地完成,但是谁知道)。

你可以解决这个问题的一种方法(也许是一种有趣的学习练习)是通过实际创建你自己的NSArray子类来完全按照你的想法来管理内存(也就是说,你可以用你想要的任何语义创建和初始化),但作为一个NSArray会对外部世界表现出来。您可以通过继承NSArray并实现方法count:objectAtIndex:来执行此操作,以便操作任何内存。显然,你需要在init/dealloc等方法中实现对自己内存的管理。见“子类别注释”下的http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html

这里的设计讨论取决于您的数据是什么样子。 NSArray当然期望它的项目是Obj-C引用(类型为id),而不仅仅是任意的数据块。如果你的C风格的数组持有结构或者其他一些不是对象引用的原始值,那么这种技术对你来说真的不起作用 - NSArray的接口永远不会满足于非引用项目。

最后一点:你提到了一个N​​SMutableArray和“创建”一个NSArray。你应该知道一个NSMutableArray已经是一个NSArray了,因为它是一个子类。你可以在任何你想要NSArray的地方使用NSMutableArray的一个实例,而不需要创建它的一个新副本。

UPDATE:错过了关于包含浮点数组的注释。是的,你在这里有点麻烦。 NSArrays需要对象。如果容量翻倍是昂贵的部分(如另一张海报注释),那么请尝试initWithCapacity :.如果是把对象类型的花车装箱/拆箱,那么你就无能为力。

我已经创建了(但没有得心应手)一对非常简单的类(称为像MYArray和MYMutableArray),旨在包装这种类型的数据与类NSArray的方法。但它们不能与NSArrays互换。你必须有意地使用它们。

UPDATE#2。我知道这个问题已经过去了很久了,但我只是重新审视它,并意识到实际上在这个具体案例中有一种巧妙的解决方法。 (你想从C样式的float数组中获得不可变的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 

(NB写在不编译/测试编辑。)

+0

谢谢!这就说得通了。 – 2010-01-03 17:11:56

3

一种优化,可以与NSMutableArray里做的是initWithCapacity这将阻止你的阵列增加了一倍这是在另外昂贵的操作。

除此之外,由于NSArrays和NSMutableArrays需要对象,因此很难解决这个问题。

0

如果可能的话,“最佳”优化(对于速度)几乎肯定会完全避免使用NSArray

1

你希望得到它作为NSArray有什么好处?

好像你可能会与C阵列周围的自定义包装对象,响应任何的NSArray消息您正在寻找致电更好。否则,你是右后卫在创建阵列的点...你可以尝试手动创建到initWithObjects一个电话,但至少是每一个浮动必须被包裹在一个NSNumber这将再次打倒你的速度。

如果你真的需要一个NSArray,因为你要使用别的东西需要NSArray的对象,那么你可能会更好过NSArray的子​​类(以下张贴本准则)。

相关问题