2010-01-03 41 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的子​​類(以下張貼本準則)。

相關問題