ちょっと、そこ! iOSやmacOS上でユーザーインターフェースを構築するためのフレームワークであるSwiftUIについてお話したいと思います。プログラミングに宣言型アプローチを採用しているため、非常に使いやすいです。 SwiftUI を使用すると、インターフェイスが何を行うべきか、どのように見えるかを記述することができ、残りはフレームワークが処理します。
SwiftUI の重要な要素の 1 つは、プロパティ ラッパーの使用です。これらは、プロパティに追加のロジックを提供できる機能要素です。
@州
@バインディング
@ObservedObject
@StateObject
@EnvironmentObject
彼らは開発においてあなたの親友になってくれるでしょう。
@State を使用すると、変更可能なプロパティを作成し、必要に応じて、これらの変更に基づいてインターフェイスを更新できます。たとえば、押されたときに色が変わるボタンを作成する場合は、色を保存する @State 変数を作成し、それをボタンに追加します。
struct MyButton: View { @State var buttonColor = Color.blue var body: some View { Button("Press me!") { buttonColor = Color.red } .background(buttonColor) } }
@Binding を使用すると、コードのある部分に格納されている値をコードの別の部分で使用できます。これは通常、あるビューから別のビューに値を渡し、相互に対話できるようにするために SwiftUI で使用されます。たとえば、2 つのビューがあるとします。1 つはテキスト フィールド、もう 1 つはボタンです。ユーザーがボタンを押したときにテキストフィールドが更新されるようにします。これを行うには、@Binding を使用します。
struct ContentView: View { @State private var text = "" var body: some View { VStack { TextField("Enter text", text: $text) Button("Update text") { text = "New text" } SecondView(text: $text) } } } struct SecondView: View { @Binding var text: String var body: some View { Text(text) } }
この例では、 @Binding を使用して$text ( ContentViewにある) からtext ( SecondViewにある) に値を渡すため、ユーザーがボタンを押すと、テキスト フィールドが更新されて新しいテキストが表示されます。
@ObservedObject は、監視され、外部データの変更に応じて変更される可能性があるプロパティをマークするために使用されます。このプロパティ ラッパーは、 ObservableObject プロトコルに準拠するオブジェクトの変更をサブスクライブし、データが変更された場合はインターフェイスの関連部分を自動的に更新します。 @ObservedObjectの使用例を簡単に示します。
class UserData: ObservableObject { @Published var name = "John" } struct ContentView: View { @ObservedObject var userData = UserData() var body: some View { VStack { Text("Hello, \(userData.name)!") TextField("Enter your name", text: $userData.name) } } }
この例では、@Published 名を含む UserData というクラスを作成します。 ContentView 構造では、 @ObservedObject を使用して、タイプ UserData の userData というプロパティを作成します。 userData.name の値をテキストフィールドに表示し、画面に出力します。
ユーザーがテキスト フィールドの値を変更すると、名前プロパティが@Published を使用して公開および監視されるため、SwiftUI はインターフェイスの対応する部分を自動的に更新します。これは、インターフェースを更新するために独自のコードが必要なく、SwiftUI がそれを行うことができることを意味します。
注意: @Published は、クラスまたは構造体のプロパティに追加できる Combine フレームワークのプロパティ ラッパーで、そのプロパティの値の変更に関する通知を、サブスクライブしているすべてのユーザーに自動的に送信します。 。言い換えれば、これは変更を追跡できるプロパティのヘルパー属性です。
@StateObject は、クラス オブジェクトを初期化し、それを SwiftUI のビューステートに保存するために使用されるプロパティ ラッパーです。これは、オブジェクトはビューが存在する限り保存され、ビューとともに破棄されることを意味します。通常、1 つのビューだけでなく複数のビューに必要なクラス オブジェクトの場合は、 @StateObjectを使用する方が実用的です。例えば:
class UserData: ObservableObject { @Published var name = "John" @Published var age = 30 } struct ContentView: View { @StateObject var userData = UserData() var body: some View { NavigationView { VStack { Text("Name: \(userData.name)") Text("Age: \(userData.age)") NavigationLink( destination: ProfileView(userData: userData), label: { Text("Edit Profile") }) } .navigationTitle("Home") } } } struct ProfileView: View { @ObservedObject var userData: UserData var body: some View { Form { TextField("Name", text: $userData.name) Stepper("Age: \(userData.age)", value: $userData.age) } .navigationTitle("Profile") } }
この例では、 UserData は、複数のビューで使用できるいくつかのプロパティを含むクラスのオブジェクトです。このクラスはObservableObjectとしてマークされているため、 @StateObjectおよび@ObservedObjectとともに使用できます。
ContentView では、 @StateObjectを使用して新しいUserDataオブジェクトを作成し、異なるビュー間の遷移間の状態を保存します。この場合、 ContentView はユーザー データを表示して視覚化し、ユーザー データの編集に使用できる別のビュー(ProfileView)へのリンクを含みます。
ProfileViewでは、 @ObservedObjectを使用して同じUserDataオブジェクトにアクセスし、ユーザー データを変更します。ユーザーがデータを変更すると、同じUserDataオブジェクトが使用されるため、 ContentViewでデータが自動的に更新されます。
注: 1 つのビューからクラス オブジェクトの変更を監視する必要がある場合は @ObservedObject を使用し、複数のビューの表示に影響するクラス オブジェクトの状態を保存する必要がある場合は @StateObject を使用します。
複数のビューで必要なオブジェクトに対して @StateObject の代わりに @ObservedObject を使用すると、各ビューがオブジェクトの独自のインスタンスを持つことになり、ビュー間のデータ同期で問題が発生する可能性があります。したがって、この場合は @StateObject を使用することをお勧めします。
@EnvironmentObject は、SwiftUI ビュー階層を介してデータ オブジェクトを渡すためのプロパティ ラッパーです。これにより、Environment コンテナ (Scene、View、App など) に属する SwiftUI 階層内の任意のビューからデータ オブジェクトにアクセスできるようになります。たとえば、タスク リスト管理アプリがあると想像してください。タスクのリストと新しいタスクを作成する機能を含むルートContentView を作成できます。このために、タスクのリストと新しいタスクを追加するボタンを表示する別のTaskListViewビューを作成します。新しいタスクを追加した後、ユーザーはタスクの追加画面にリダイレクトされる必要があるため、別のAddTaskViewビューを作成します。
UserManagerオブジェクトを 3 つのビューすべてに渡すには、 ContentViewでそのインスタンスを作成し、それをパラメータとしてTaskListViewとAddTaskViewの両方に渡すことができます。ただし、ネストされたビューをさらに追加する場合は、多くの中間ビューを介してUserManagerを渡す必要があるため、これが問題になる可能性があります。
この代わりに、 @EnvironmentObjectを使用して、ビュー階層を通じてUserManagerを渡すことができます。こうすることで、 UserManagerにアクセスする必要があるすべてのビューは、UserManager を@EnvironmentObjectとして宣言し、必要に応じて使用するだけで済みます。
struct TaskManagerApp: App { @StateObject var userManager = UserManager() var body: some Scene { WindowGroup { ContentView() .environmentObject(userManager) } } } struct ContentView: View { var body: some View { NavigationView { TaskListView() } } } struct TaskListView: View { @EnvironmentObject var userManager: UserManager var body: some View { List(userManager.tasks) { task in TaskRow(task: task) } .navigationBarTitle("Tasks") .navigationBarItems(trailing: Button(action: { // Navigate to AddTaskView }) { Image(systemName: "plus") } ) } } struct AddTaskView: View { @EnvironmentObject var userManager: UserManager var body: some View { // Add new task using userManager } }
したがって、 UserManagerオブジェクトは@EnvironmentObjectを介してTaskListViewおよびAddTaskViewに自動的に渡されます。 1 つのビューでUserManagerの状態を変更でき、その変更は自動的にもう 1 つのビューに反映されることに注意してください。
この記事では、基本的な SwiftUI プロパティ ラッパー、 @State、@Binding、@ObservedObject、@StateObject、@EnvironmentObject について説明しました。
これらのプロパティ ラッパーは、SwiftUI でアプリの状態を操作するための基礎を形成します。この記事をチートシートとして使用して、SwiftUI でアプリを開発するために必要な基本的なプロパティ ラッパーをすぐに利用できるようにします。この知識を適用すると、状態が動的に変化するより複雑なユーザー インターフェイスを構築し、モデルのデータを SwiftUI に統合できるようになります。