気をつけることと両者の違い
結論から言うと、気をつけるべきことは、クラスの性質
と構造体の性質
に注意するということ。
また、両者の違いは、主にUIkitはクラスでViewが作成され、SwiftUIは構造体でViewが作成される
ことである。
このトピックにおけるUIKitの性質
-
クラスの生成
- 通常、クラスで作成したインスタンスは、アプリのライフサイクル内で一度生成されると、(自分でインスタンスを破棄するコードを書くなど以外で)
そのインスタンスはほとんど破棄されることはなく保持される。
そのため、データや設定が安定して維持される。
- 通常、クラスで作成したインスタンスは、アプリのライフサイクル内で一度生成されると、(自分でインスタンスを破棄するコードを書くなど以外で)
-
いつクラスのインスタンスが破棄されるのか?
- 通常は、
ViewController自体が破棄されるときに一緒に破棄される。
- 破棄されるタイミングの具体例
- ユーザーが画面上の戻るボタンを押して前の画面に戻ると、現在のビューコントローラーが破棄される。
- メモリ不足の状況下で、システムがビューコントローラーとそのビューを解放し、メモリを開放することがある。
- 破棄されるタイミングの具体例
- ただし、具体的な破棄タイミングはシステムに依存し、
アプリのコードで直接制御することは難しいことが多い。
したがって、破棄のタイミングは開発者側は詳しくは分からないことがある。
- 通常は、
このトピックにおけるSwiftUIの性質
- 再描画の度に新しいViewのインスタンスを生成するため、View内でインスタンス(クラスで作成した)を作成する場合、再生成の際に新しいインスタンスが作成される。
ソースコード
再描画によってテキスト(データ)が消える実装
Swift
struct ContentView: View {
// クラスを用いてユーザーのテキスト入力を保持する
class UserData {
var userInput = ""
}
// UserDataクラスのインスタンス
// 再描画の度に新しいuserDataインスタンスが生成されるから、前に入力されたユーザーの入力が再描画時に消えてしまう
@State var userData = UserData()
var body: some View {
VStack {
Text("テキストフィールドに入力したテキスト: \(userData.userInput)")
TextField("テキストを入力してください", text: $userData.userInput)
}
}
}
@Stateプロパティーラッパーを使って、状態管理をして、再描画時にもデータが失われないようにする
Swift
struct ContentView: View {
// ユーザーがテキスト入力をすると、@Stateプロパティによって追跡される
// その結果、再描画時にも状態が保持され、入力内容も消えない
@State var userInput = ""
var body: some View {
VStack {
Text("テキストフィールドに入力したテキスト: \(userInput)")
TextField("テキストを入力してください", text: $userInput)
}
}
}
おわりに
間違い等ありましたらコメント欄にてご指摘ください!
参考記事
開発環境
- Xcode-14.3
- Swift version 5.8