4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Posted at

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

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

  • 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

4
4
0

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
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?