NSMutableArray'ı NSArray'e nasıl dönüştürebilirim?


Yanıtlar:


511
NSArray *array = [mutableArray copy];

Copydeğişmez kopyalar yapar. Bu oldukça kullanışlıdır çünkü Apple çeşitli optimizasyonlar yapabilir. Örneğin copydeğişmez bir diziye göndermek sadece nesneyi korur ve geri döner self.

Çöp toplama veya ARC kullanmıyorsanız -copy, nesneyi koruduğunu unutmayın .


2
bu cevap harika, ancak copynormal bir NSArray oluşturan ve bir NSMutableArray oluşturan dokümanlardan nasıl anlatabilirim ?
Dan Rosenstark

22
@Yar: NSCopying belgelerine bakıyorsunuz Burada şunu belirtiyor: copyWithZone “Kopyalanamaz veya değişebilir” dikkate alınan nesne için geçerliyse, döndürülen kopya değiştirilemez; aksi takdirde kopyanın kesin niteliği sınıf tarafından belirlenir.
Georg Schölly

1
Çok temiz - Bunu m5h çözümüne tercih ederim. Hem kısa hem de daha verimli.
David Snabel-Caunt

1
David'e katılıyorum, bu yanıta işaret etmek için cevabımı güncelledim.
hallski

2
@Brad: Bu, hem değişebilir hem de değişmez uygulamalara sahip sınıflar anlamına gelir. Örn. NSArray& NSMutableArray, NSString& NSMutableString. Ancak, örneğin NSViewControllerher zaman değişebilir durum içeren değil .
Georg Schölly

361

An NSMutableArray, NSArrayher zaman dönüştürmeniz gerekmeyecek bir alt sınıftır, ancak dizinin değiştirilemeyeceğinden emin olmak istiyorsanız, otomatik NSArrayolarak yayınlanıp yayınlanmamasına bağlı olarak aşağıdaki yollardan birini oluşturabilirsiniz :

/* Not autoreleased */
NSArray *array = [[NSArray alloc] initWithArray:mutableArray];

/* Autoreleased array */
NSArray *array = [NSArray arrayWithArray:mutableArray];

DÜZENLEME: Georg Schölly tarafından sağlanan çözüm , bunu yapmanın daha iyi bir yolu ve çok daha temiz, özellikle de artık ARC'ye sahibiz ve otomatik yayınlama bile gerekmiyor.


7
(NSArray *) myMutableArray'ımı yapabilir miyim?
Vojto

2
Evet, NSMutableArray geçerli bir NSArray alt sınıfı olduğundan.
hallski

4
Ancak, (NSArray *) öğesine yayın yapmak yine de (NSMutable *) öğesine kadar yayın yapılmasına izin verir. Durum böyle değil mi?
sharvey

1
@sharvey: Evet, doğru. Doğrudan alt sınıfa atmazsanız ancak üst sınıfa atarsanız bir uyarı alırsınız. Genellikle, değişmez bir kopyayı döndürmek istersiniz, çünkü dizinizin gerçekten değiştirilmeyeceğinden emin olmanın tek yolu budur.
Georg Schölly

1
Eski adıyla "Upcasting" (NSArray *) myMutableArray olarak bilinir ve tersi "Downcasting" olarak adlandırılır
Francisco Gutiérrez

113

Her iki ana çözümden de hoşlanıyorum:

NSArray *array = [NSArray arrayWithArray:mutableArray];

Veya

NSArray *array = [mutableArray copy];

En önemli fark Onlara gördüğünüz mutableArray nil olduğunda nasıl davrandığı olduğu :

NSMutableArray *mutableArray = nil;
NSArray *array = [NSArray arrayWithArray:mutableArray];
// array == @[] (empty array)

NSMutableArray *mutableArray = nil;
NSArray *array = [mutableArray copy];
// array == nil

Bu çok yanlış. Yeni kontrol edildi. [mutableArray copy] ayrıca boş bir dizi döndürür.
durazno

@durazno Yanlış değil. Testinizi iki kez kontrol edin. [MutableArray copy] boş bir dizi döndürüyorsa, mutableArray boş bir dizi olmalıdır. Cevabım sadece mutableArray sıfır olduğunda geçerlidir.
Richard Venable

Bu doğru olsa da, örneğinizde daha temel bir gerçeği kaçırıyor gibi hissediyorum. MutableArray öğesini nil olarak atadığınız [mutableArray copy]için basitleştirilebilir [nil copy]. Hedef-c'de nil'e gönderilen herhangi bir mesaj her zaman sıfır olacaktır. "Hiçbir şey" ile "içinde hiçbir şey olmayan bir dizi" arasındaki farkı hatırlamak önemlidir.
mkirk

@mkirk Eldeki sorudan uzaklaşmayalım: "NSMutableArray'ı NSArray'e nasıl dönüştürebilirim?" 2 birincil çözüm vardır ve aralarındaki birincil fark, değişebilen dizi sıfır olduğunda nasıl davrandıklarıdır.
Richard Venable

18

bu kodu deneyin ---

NSMutableArray *myMutableArray = [myArray mutableCopy];

ve

NSArray *myArray = [myMutableArray copy];

Diğerlerinin yapmadığı bu ne yapar?
Ben Leggiero

5

Objective-C

NSMutableArray'ı NSArray'e dönüştürmenin yolu:

//oldArray is having NSMutableArray data-type.
//Using Init with Array method.
NSArray *newArray1 = [[NSArray alloc]initWithArray:oldArray];

//Make copy of array
NSArray *newArray2 = [oldArray copy];

//Make mutablecopy of array
NSArray *newArray3 = [oldArray mutableCopy];

//Directly stored NSMutableArray to NSArray.
NSArray *newArray4 = oldArray;

hızlı

Swift 3.0'da yeni veri türü Array var . Array letanahtar sözcüğünü kullanarak bildirirse NSArray olur ve varanahtar kelime kullanarak bildirilirse NSMutableArray olur .

Basit kod:

let newArray = oldArray as Array

Swift kısmı tamamen doğru değil. Değişebilir / değişmez s ve / s arasındaki fark için buraya ve buraya bakınız . Aynı değiller. ArrayNSArrayNSMutableArray
Bruno Ely

3

Hedef-c'de:

NSArray *myArray = [myMutableArray copy];

Hızlı:

 var arr = myMutableArray as NSArray

2
NSArray *array = mutableArray;

Bu [mutableArray copy]antipattern tüm örnek kod üzerindedir. Geçici olan ve geçerli kapsamın sonunda yer değiştirilebilen sabit değişken diziler için bunu bırakın.

Çalışma zamanının, kapsam dışına çıkmak üzere olan, 0'a devredilen ve iyilik için ayrılmış olan değişken bir dizinin savurgan kopyalamasını optimize etmesinin bir yolu yoktur.


NSMutableArrayBir NSArraydeğişkene a atanması değişmez (OP'nin sorusu budur). Böyle bir değerin (örneğin, bir dönüş değeri veya bir özellik olarak) gösterilmesi, bu değer beklenmedik bir şekilde mutasyona uğramışsa sorunların ayıklanmasının çok zor olmasına neden olabilir. Değişken değer paylaşıldığı için bu hem iç hem de dış mutasyonlar için geçerlidir.
David Rönnqvist

Bu diziyi değiştirmek için [NSMutableArray arrayWithArray: ... veya bunun gibi bir şey yapmanız gerekir.
Anton Tropashko

Şart değil. Basitçe bir NSMutableArraydeğişkene atamak yeterlidir. Nesne değişebilir bir dizi olmayı asla bırakmadığından, üzerinde mutasyon yöntemlerini çağırmak başarılı verileri değiştirir ve değiştirir. Öte yandan, orijinal mutable dizi kopyalanır - değiştirilemez bir dizi olarak değiştirilir ve daha sonra bir NSMutableArraydeğişkene atanır ve üzerinde mutasyon yöntemleri çağrılırsa doesNotRespondToSelector, mutasyon yöntemi çağrısını alan nesne içinde olduğundan bu çağrılar hatalarla başarısız olur gerçek değişmez ve bu yöntemlere cevap vermez.
David Rönnqvist

tamam, bu yazım dönüştürme varsayımları hakkında derleyici uyarısı dikkate almaz geliştiriciler için bazı değer olabilir
Anton Tropashko

1

Değişebilirlik yoluyla bir dizi oluşturuyorsanız ve ardından değiştirilemez bir sürüm döndürmek istiyorsanız, değiştirilebilen diziyi kalıtım yoluyla bir "NSArray" olarak döndürebilirsiniz.

- (NSArray *)arrayOfStrings {
    NSMutableArray *mutableArray = [NSMutableArray array];
    mutableArray[0] = @"foo";
    mutableArray[1] = @"bar";

    return mutableArray;
}

(Teknik olarak hala değiştirilebilir) dönüş nesnesini değişmez bir NSArray olarak işlemek için arayana "güvenirseniz", bu daha ucuz bir seçenektir [mutableArray copy].

Apple aynı fikirde:

Alınan bir nesneyi değiştirip değiştiremeyeceğini belirlemek için, bir iletinin alıcısının dönüş değerinin biçimsel türüne bağlı olması gerekir. Örneğin değişmez olarak yazılan bir dizi nesnesi alırsa, onu değiştirmeye çalışmamalıdır . Bir nesnenin sınıf üyeliğine göre değiştirilebilir olup olmadığını belirlemek kabul edilebilir bir programlama uygulaması değildir.

Yukarıdaki uygulama burada daha ayrıntılı olarak tartışılmaktadır:

En İyi Uygulama: Dönüş türü NSArray ise Return mutableArray.copy veya mutableArray


0

hızlı 3 cevap aramak oldu ve bu soru arama ilk sonuç olarak gösterildi ve burada hızlı 3 kodu işte cevap ilham

let array: [String] = nsMutableArrayObject.copy() as! [String]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.