swiftui

iOSアプリ開発

StateとObservableを使ってSwiftUIのビューを変更する方法

SwiftUIフレームワークを使っているとStateやObservedObjectと言った機能がよく使われています。特に、勉強を始めた頃などは「この機能が何をしているのか」や「どうやって使えばいいの?」と言った疑問があると思います。今回は、これらの機能についてわかりやすく解説していきます。

SwiftUIとは

今までiOSアプリ開発で使ってきたUIKitよりも、より簡単でインタラクティブにUIを実装できるようにしたフレームワークです。SwiftUIは設計自体が変わっていて、階層化されていてUIの配置がわかりやすくなっていたり、レイアウトなどを調整してくれるようになっていたり、デザインの変更が簡単にできるようにインターフェースがわかりやすくなっています。詳しくは、以下の記事を読んでみてください。

Stateとは

Property Wrappersで実装されていて、SwiftUIが提供しているAttributeの1つです。ビューに@Stateをつけた変数に変更があると、その時点でビューを更新するようになっています。Webのフロントエンドを開発している人は、ReactやVueで使われているStateプロパティに近いものと考えるとわかりやすいと思います。

@State var isSelected: Bool = false

Property Wrappersとは

State属性はProperty Wrappersという機能で実装されたものと説明しました。では、このProperty Wrappersとはなんでしょうか。この機能はAttributeを宣言する機能で、@を使ってプロパティの更新や取得時に何らかの処理を加えることができます。Stateは、値の更新時にUIの更新をする機能を持っていると言えます。

  • Attributeを宣言する機能で@を使ってアクセスできるようになる
  • Attributeはプロパティにつけるとことで特定の機能を持たせることができる
  • @ を使用することでプロパティへの独自のアクセスを提供する
  • @State @ObservedObject @Published などがあげられる

State属性を実際に使ってみる

State属性は以下のような機能を持っています。

  • @Stateをつけたプロパティに変更があるとその時点でUIを更新する
  • ReactやVueのStateプロパティに近い
  • $をつけることで本来の値にアクセスができる
  • 値はSwiftUIが持つStoreに保持される

この機能を利用して、ビューの色をかえるサンプルを実装してみます。


import SwiftUI

struct StateSampleView: View {
    @State var isSelected: Bool = false

    var body: some View {
        VStack {
            Button(action: {
                self.isSelected = !self.isSelected
            }) {
                Text("Change Color")
            }

            Circle().foregroundColor(isSelected ? .blue : .yellow)
        }
    }
}

ObservedObjectとは

State属性と似たようなAttributeに、ObservedObject属性というものがあります。ObservedObjectは、ObservableObjectプロトコルを適用したクラスを監視することができるようにします。ObservableObjectは、Combineフレームワークの機能の1つです。Combineは、非同期にイベントを処理するためのフレームワークです。ObservableObjectは、ReactiveプログラミングのSubscriberと同じような役割を持ています。以下のようなことができます。

  • 実装したクラスやモデルが持つプロパティを監視する
  • 監視しているプロパティが更新されると変更が通知される
  • ObservableObjectを適用したクラスの一部実装にPublished属性を利用することができる

ユースケースと実装例

今回は、ボタンを押すとサークルの色が変わるサンプルを実装してみます。内容は、Modelの値の変更を監視して変化したらサークルの色を更新というシンプルなものです。

モデルの実装は以下のようになります。変更があった場合に、objectWillChangeという値に通知を送ることでビューに伝達することができます。


import Foundation
import Combine

class ObservableModel: ObservableObject {
    var objectWillChange = PassthroughSubject<observablemodel, never="">()

    var isSelected: Bool = false {
        didSet {
            self.objectWillChange.send(self)
        }
    }
}

ビューの実装は以下のようになります。変更があると、ObservedObject属性を付与しているmodelに通知が行き、ビューを更新します。


import Foundation
import SwiftUI
import Combine

struct ObservableSampleView: View {
    @ObservedObject(initialValue: ObservableModel()) var model: ObservableModel

    var body: some View {
        VStack {
            Button(action: {
                self.model.isSelected = !self.model.isSelected
            }) {
                Text("Change Color")
            }
            Circle().foregroundColor(model.isSelected ? .blue : .yellow)
        }
    }
}

ObservedObjectは初期化する方法が2つある

最後に、ObservedObjectを付与したプロパティの初期化方法を紹介します。

ビューのinitの引数として渡す

1つ目は、ビューの初期化時に引数として渡してあげる方法です。


struct ObservableSampleView: View {
    @ObservedObject var model: ObservableModel
}

let view = ObservableSampleView(model: ObservableModel())

ObservableのinitialValueを使う

1つ目は、ビューの初期化時に引数として渡してあげる方法です。


struct ObservableSampleView: View {
    @ObservedObject(initialValue: ObservableModel()) var model: ObservableModel
}

swiftui初心者でもiOSアプリ開発ができるSwiftUIを触ってみようPrev

Firebase Firestoreを使ってiOSアプリのデータを管理する方法Next

Related post

  1. iOSアプリ開発

    IBDesignable、IBInspectableを使ってStoryboardでデザインする方法

    iOSアプリ開発をStoryboardを使って開発している方も増えてき…

  2. iOSアプリ開発

    SwiftでJSONデータを使いやすくする!Codableの使い方

    APIからデータを取得する時、JSONでデータを受け取ることがあるかと…

  3. iOSアプリ開発

    Firebase Firestoreを使ってiOSアプリのデータを管理する方法

    アプリを作る・サービスを立ち上げるといったとき、ほとんどの場合はDBや…

  4. iOSアプリ開発

    DispatchQueueを使って容量のあるファイルをダウンロードする方法

    アプリなどで画像のようなファイルデータをダウンロードすることはよくあり…

  5. itunes connect

    iOSアプリ開発

    初心者向けにiOSアプリ開発からリリースまでの手順を丁寧に解説!

    iPhoneやiPadのアプリ作ってリリースをしてみたいけれど、実際に…

  6. dark-mode

    iOSアプリ開発

    iOSアプリでダークモードに対応する様々な方法

    アプリやOSのUIを全体的に黒を基調としたデザインにする機能で、201…

PAGE TOP