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
}

Related post

  1. iOSアプリ開発

    iOSアプリでFirestoreを使ってデータを保存しよう

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

  2. テクノロジー

    Appleの新しいMessagesで何ができるのか。

    WWDC 2016では数多くのセッションが行われました。WWDC 20…

  3. iOSアプリ開発

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

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

  4. swiftui

    iOSアプリ開発

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

    「アプリ開発って難しそう」「アプリを作ってみたいけど作り方がわからない…

  5. Pythonでスクレイピング

    BeautifulSoup4でid, classを持つDOMを取得して効率化しよう!

    前回は、"スクレイピングでヘッダー情報を付与する方法とその目的"を紹介…

  6. テクノロジー

    iOSアプリ開発が簡単にできるStoryboard入門

    iOSアプリを開発しようとXcodeをダウンロードしてプロジェクト作成…

PAGE TOP