Swiftには二つの基本的なデータ型があります:値型(value types)と参照型(reference types)。
struct)、列挙型(enum)、および基本的な型(Int、Double、Boolなど)が含まれます。値を渡したり代入したりするとき、値はコピーされるため、コピーの変更は元のものには影響しません。class)およびそれに関連する型です。渡されたものはオブジェクト自体ではなく、オブジェクトへの参照ですので、一つの参照を通じた変更は他の参照からも見えるようになります。使用するタイミング:
CGPoint、CGSize、状態を共有してはならないモデルなど)。例:
struct Point { var x: Int var y: Int } class Person { var name: String init(name: String) { self.name = name } } var p1 = Point(x: 0, y: 0) var p2 = p1 p2.x = 10 // p1.xは0のまま var person1 = Person(name: "Alex") var person2 = person1 person2.name = "Sam" // person1.nameも"Sam"になる
letを使った構造体とクラスの違いは何ですか? letで作成されたclassのインスタンスは完全に不変ですか?
回答:
値型(struct)に対しては、letがオブジェクトとそのプロパティを不変にします。
参照型(class)に対しては、letが参照を再割り当てすることを禁止しますが、オブジェクトのプロパティは保護されません。それらは、クラス内でletとして声明されていない限り変更可能です。
例:
class Box { var value: Int init(value: Int) { self.value = value } } let box = Box(value: 10) box.value = 20 // OK! // box = Box(value: 30) // エラー:boxを再割り当てできません
物語
支払いアプリケーションではトランザクションモデルをクラスとして定義しましたが、状態は存在しないはずでした。バグが発生しました:トランザクションリストの同時操作中に異なる画面のデータが予測不可能に編集されました。各コンポーネントが独自のコピーで作業するようにモデルを構造体へ移行することに決定しました。
物語
プロジェクトではユーザー設定をクラスに保存し、値は渡すことでコピーされると思っていました。データを変更すると、一つの画面が意図せず他の画面に影響を与えました。なぜなら、両方とも同じオブジェクトへの参照で作業していたからです。
物語
シリアル化モジュールではモデルデータを参照型として宣言したため、どんな変更もキャッシュの状態を破壊していました。値型に置き換えた後、問題は解決されました:データは各操作で独立するようになりました。