2013-05-31 126 views
2

我已經閱讀了許多SO帖子,然後問這個問題,我猜這個答案在那裏,但我沒有看到它。我是Objective-C的新手,我試圖做一個我看不出來的(看似)簡單的操作。Objective-C:拷貝數組,修改拷貝中的元素(對象)

總的想法是,我有一個NSArray填充對象(特別是類型UIImageView)。我想複製該數組,我已經完成了許多方法(全部成功)。

複製完成後,我現在有兩個數組。我想修改一個對象,比如索引2,,只有在副本中。

到目前爲止,似乎等,因爲複製僅僅複製參考(或指針),改變對象在索引2將改變它在二者複製原稿。

這有道理嗎?

NSArray *originalArray = @[object1, object2]; 

的方法,我已經試過複製此陣,這樣我就可以達到我想要的:

NSMutableArray *originalArrayCopy = [NSMutableArray arrayWithArray:originalArray]; 

NSArray *originalArrayCopy = [originalArray copy]; 

NSMutableArray *originalArrayCopy = [[NSMutableArray alloc] initWithArray:originalArray]; 

它似乎在每種情況下,從複製修改對象還修改它原本的。

注:雖然NSArray顯然是不可變的,我原來的陣列內的對象是可變的。

回答

8

如果你的數組中的元素符合NSCopying協議,你可以這樣做:

NSMutableArray *copy = [[NSMutableArray alloc] initWithArray:originalArray copyItems:YES]; 

這有發送copy原來的陣列中的每個元素,存儲副本的新數組中的作用。

這是好的,如果各元件當它接收到消息copy返回一個新的,可變的副本。但是,幾個基礎類(如NSMutableArrayNSMutableString)在收到copy消息時會返回不可變副本。如果您的元素屬於這樣的類別,則需要發送mutableCopy消息。

沒有內置的公共信息,以做到這一點。您可以手動像這樣做:

NSMutableArray *copy = [[NSMutableArray alloc] initWithCapacity:originalArray.count]; 
for (id element in originalArray) { 
    [copy addObject:[element mutableCopy]]; 
} 
+0

是的,第二個解決方案是有意義的。然而,我在我的問題中犯了一個錯誤,因爲我沒有指定我的原始數組中的元素是UIImageView類型。我知道這讓事情變得更具挑戰性。在嘗試第二種解決方案時,我收到錯誤:'NSInvalidArgumentException [UIImageView mutableCopywithZone:]' – codework

+0

每個UIImageView對象都是我的一個類的屬性。 – codework

+0

請編輯您的問題,解釋您爲什麼要複製圖像視圖。你將把它們放在你的視圖層次結構中? –

0

是的,所有隻會複製數組。您的複製數組仍將引用相同的對象。

我不認爲(或者只是不知道如何),你可以一次性複製所有包含的對象。我猜你必須迭代原始數組中的對象,複製每個對象並將其副本添加到新創建的並且最初爲空的可變數組中。 如何複製這些對象很大程度上取決於這些對象的性質以及複製這些對象的目的。

是的,沒有理由爲什麼不可變數組中的對象也應該是不可變的。

1

這使得第一NSArray中的深拷貝到第二的NSMutableArray:

NSArray *firstArray = [NSArray arrayWithObjects:@"foo", @"bar",nil]; 
NSMutableArray *secondArray = [[NSMutableArray alloc]initWithArray:firstArray copyItems:YES]; 
1

只要你要複製實現NSCoding協議的對象

(void)encodeWithCoder:(NSCoder *)encoder; 
(id)initWithCoder:(NSCoder *)decoder; 

,你可以做任何對象的深層副本這樣

NSArray *originalArray = @[object1, object2]; 
NSMutableArray *deepCopy = [NSkeyedUnarchiver unarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject: originalArray]];