search
LoginSignup
4
Organization

SwiftUIでダイアログを実装する(例:ローディング)

すべてのコンテンツ上でローディングダイアログを表示

以下の「モデルクラス」と「モディファイア」を導入することで、すべてのコンテンツ上でローディングダイアログを表示します。

  • DialogModel.swift
  • DialogModifier.swift

DialogModel

ObservableObjectプロトコルに準拠したクラスです。
これを使用して、ダイアログをアクティブ・非アクティブします。

DialogModel.swift
import Foundation

public enum DialogType {
    case none
    case loading
}

class DialogModel: NSObject, ObservableObject {
    @Published var dialogType: DialogType = .none
}

Dialog モディファイア

DialogModelのdialogTypeに基づいてローディングダイアログをアクティブにします
オーバーレイは、ビューをコンテンツの上に配置するために使用されます

DialogModifier.swift
import SwiftUI

struct DialogModifier: ViewModifier {
    @ObservedObject var dialogModel: DialogModel
    
    func body(content: Content) -> some View {
        content
            .overlay(
                Group {
                    switch dialogModel.dialogType {
                    case .loading:
                        VStack {
                            Text("Loading...")
                            ActivityIndicator(isAnimating: .constant(true), style: .large)
                        }
                        
                    default:
                        EmptyView()
                    }
                }
            )
    }
}

extension View {
    func dialog(_ model: DialogModel) -> some View {
        self.modifier(DialogModifier(dialogModel: model))
    }
}

struct ActivityIndicator: UIViewRepresentable {
    
    @Binding var isAnimating: Bool
    let style: UIActivityIndicatorView.Style
    
    func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView {
        return UIActivityIndicatorView(style: style)
    }
    
    func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext<ActivityIndicator>) {
        isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
    }
}

Dialog モディファイアを適用する

一番上の親ビューにDialogModelを生成し、@StateObjectで保持する
そして、この親ビューに.environmentObjectでDialogModelをセットし、DialogModifierを適用する
これで、DialogModelのdialogTypeを指定することで、アプリのコンテンツビュー(一番トップの親ビュー)からダイアログが表示されるようになります。

オーバーレイは、アタッチされているビューにのみ適用されます。 そのため、「ダイアログ」を他のすべてのコンテンツ上に表示するには、一番上の親ビューにオーバーレイを配置する必要があります。

TDDApp.swift
import SwiftUI

@main
struct TDDApp: App {
    
    // アプリ起動時にDialogModelをインスタンス
    @StateObject var dialogModel = DialogModel()

    var body: some Scene {
        WindowGroup {
            ContentView()
            // アプリのコンテンツビュー(一番トップの親ビュー)に共有オブジェクトとして登録し、ダイアログのモディファイアを適応
                .environmentObject(dialogModel)
                .dialog(dialogModel)
        }
    }
}

ローディングダイアログを表示する

ダイアログを表示したいビューにDialogModelを取り込みます

    @EnvironmentObject var dialogModel: DialogModel

その後、ダイアログを表示したいビューでローディングダイアログを表示

    self.dialogModel.dialogType = .loading

その後、ダイアログを消す

    self.dialogModel.dialogType = .none

参考

GitHub

TDD

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
4