Swiftの不変/可変コレクション


88

Swift言語での可変/不変オブジェクト(配列、辞書、セット、データ)の作成を理解するために、AppleのSwiftプログラミングガイドを参照していました。しかし、Swiftで不変のコレクションを作成する方法を理解できませんでした。

Objective-Cで次のSwiftに相当するものを見たいです

不変の配列

NSArray *imArray = [[NSArray alloc]initWithObjects:@"First",@"Second",@"Third",nil];

可変配列

NSMutableArray *mArray = [[NSMutableArray alloc]initWithObjects:@"First",@"Second",@"Third",nil];
[mArray addObject:@"Fourth"];

不変の辞書

NSDictionary *imDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:@"Value1", @"Key1", @"Value2", @"Key2", nil];

可変辞書

NSMutableDictionary *mDictionary = [[NSMutableDictionary alloc]initWithObjectsAndKeys:@"Value1", @"Key1", @"Value2", @"Key2", nil];
[mDictionary setObject:@"Value3" forKey:@"Key3"];

回答:


115

配列

不変の配列を作成する

最初の方法:

let array = NSArray(array: ["First","Second","Third"])

2番目の方法:

let array = ["First","Second","Third"]

可変配列を作成する

var array = ["First","Second","Third"]

オブジェクトを配列に追加します

array.append("Forth")


辞書

不変の辞書を作成する

let dictionary = ["Item 1": "description", "Item 2": "description"]

可変辞書を作成する

var dictionary = ["Item 1": "description", "Item 2": "description"]

新しいペアを辞書に追加する

dictionary["Item 3"] = "description"

AppleDeveloperの詳細


12
「固定長」配列の方が正確です。それは不変ではありません。
スルタン2014年

1
不変Dictionaryは本当に不変です(アレイの反対)
Bryan Chen

@BryanChenああ..ありがとう!
nicael 2014年

@BryanChenうん、削除するのを忘れたvar
nicael 2014年

2
うん。この質問とその回答の配列の不変性に関する詳細情報。
マットギブソン

31

Swiftの代わりにドロップはありません NSArray、Objective-Cのまたは他のコレクションクラスの。

配列クラスと辞書クラスがありますが、これらは「オブジェクト」タイプであるNSArrayおよびNSDictionaryと比較して、「値」タイプであることに注意してください。

違いは微妙ですが、エッジケースのバグを回避するために非常に重要な場合があります。

迅速に、次のようにして「不変」配列を作成します。

let hello = ["a", "b", "c"]

そして、次のような「可変」配列:

var hello = ["a", "b", "c"]

可変配列は、次のように変更できます。 NSMutableArray

var myArray = ["a", "b", "c"]

myArray.append("d") // ["a", "b", "c", "d"]

ただし、可変配列を関数に渡すことはできません。

var myArray = ["a", "b", "c"]

func addToArray(myArray: [String]) {
  myArray.append("d") // compile error
}

ただし、上記のコードはNSMutableArrayで機能します。

var myArray = ["a", "b", "c"] as NSMutableArray

func addToArray(myArray: NSMutableArray) {
  myArray.addObject("d")
}

addToArray(myArray)

myArray // ["a", "b", "c", "d"]

メソッドパラメータNSMutableArrayを使用して、の動作を実現できinoutます。

var myArray = ["a", "b", "c"]

func addToArray(inout myArray: [String]) {
  myArray.append("d")
}

addToArray(&myArray)

myArray // ["a", "b", "c", "d"]

現在のSwiftの動作を反映するために、この回答を2015-08-10に書き直しました。


1
これは明らかに変更されました。定数配列は真に不変になり、可変配列は真に可変になりました。これらはとして渡されるため、別の変数に割り当てられたとき、または関数間で渡されたときにコピーされます。ただし、これは可変性または不変性とは何の関係もありません。
バルタザール2015

また、私の回答で述べたように、値として渡されることは、配列を他のコード(変更する可能性がある)に渡すときだけ気にするので、可変性/不変性に関連しています。
Abhi Beckert 2015

ただし、配列にプロパティとしてアクセスする場合でも、別のオブジェクトから配列を変更できます。不変配列の利点の1つは、他のオブジェクトが元のオブジェクトを変更する可能性があるかどうかを心配することなく、他のオブジェクトに安全に渡すことができることです。オブジェクトが値として渡される場合、この懸念はもはや存在しません。したがって、セマンティクスが異なれば、コーディング方法も異なります。編集:あなたが投稿を書き直したことがわかりましたので、同意します。私は違いがwrtを認識するために重要であることに同意します。可変コレクションの使用。
バルタザール2015

6

SwiftにはArray1つのDictionaryタイプしかありません。可変性は、それをどのように構築するかによって異なります。

var mutableArray = [1,2,3]
let immutableArray = [1,2,3]

つまり、変数への割り当てを作成する場合は変更可能ですが、定数への割り当てを作成する場合は変更できません。

警告:不変の配列は完全に不変ではありません!全体の長さだけでなく、内容を変更することもできます。


1
参考:アレイの動作は、今後のベータ版で変更されます。私は誰もがそれについて積み上げたと思います
russbishop 2014年

@xenaduソース?そのベータ版のETA?
アナログファイル

申し訳ありませんが、ソースはありません。これは、コンパイラチームのメンバーの1人との話し合いから生まれました。彼はまた、ベータ2は基本的に、すでにチェックインされているバグ修正のほんの2、3であり、WWDC後のフィードバックとは何の関係もないと述べました。
russbishop 2014年

5

(任意の)オブジェクトまたは変数をで宣言するだけです

'let' key word -> for "constan/Immutable" array, dictionary, variable, object..etc.

そして

'var' key word -> for "Mutable" array, dictionary, variable, object..etc. 

より詳細な情報について

letを使用て定数を作成し、varを使用して変数を作成します。定数の値はコンパイル時に知る必要はありませんが、値を1回だけ割り当てる必要があります。つまり、定数を使用して、一度決定した値に名前を付けることができますが、多くの場所で使用できます。」

var myVariable = 42
myVariable = 50
let myConstant = 42

「Swiftプログラミング言語」を読んでください。


さて、配列の場合、これは期待どおりに機能しません。stackoverflow.com/a/24319712/623710
macshome 2014年

3

のようにArray(Swift)を操作したい場合NSArrayは、単純なブリッジ関数を使用できます。例:

var arr1 : Array = []

arr1.bridgeToObjectiveC().count

についても同じように機能しletます。


0

Apple自身のドキュメントから:

コレクションの可変性

配列、セット、またはディクショナリを作成して変数に割り当てると、作成されるコレクションは変更可能になります。これは、コレクション内のアイテムを追加、削除、または変更することにより、コレクションの作成後にコレクションを変更(または変更)できることを意味します。逆に、配列、セット、またはディクショナリを定数に割り当てると、そのコレクションは不変であり、そのサイズと内容を変更することはできません。

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-ID105

不変/可変コレクションの他の使用法は、コレクションを可変/不変にする理由によって異なります。コレクションはSwiftの型です。つまり、コレクションは、別の値に割り当てられたとき、または別の関数/メソッドに渡されたときにコピーされます。したがって、受信メソッド関数が元の配列を変更する可能性があるかどうかを心配する必要はありません。したがって、たとえば、クラスが可変コレクションを保持している場合は、不変コレクションを返すようにする必要はありません。


0

[変更不可および不変]

Swiftの配列はミュートできます

[let vs var、Value vs Reference Type]

不変コレクション[概要] -コレクション構造は変更できません。これは、作成後に追加、削除、変更できないことを意味します

let + struct(のようArraySet、、Dictionary)が不変であることがより好適です

NSArray内部状態を変更するためのインターフェースを提供しないクラス(例)がいくつかあります

だが

class A {
    var value = "a"
}

func testMutability() {
    //given
    let a = A()
    
    let immutableArr1 = NSArray(array: [a])
    let immutableArr2 = [a]
    
    //when
    a.value = "aa"
    
    //then
    XCTAssertEqual("aa", (immutableArr1[0] as! A).value)
    XCTAssertEqual("aa", immutableArr2[0].value)
}   

それはむしろunmodifiable配列です

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.