IT アプリ開発

【SwiftUI】バックグラウンド処理を実装しよう!

2021年12月30日

バックグラウンドとは、アプリ自体起動しているが、画面上に表示されていない状態のことを言います。
対してフォアグラウンドとは、アプリ自体起動していて、今画面上に表示されている状態のことを言います。
このフォアグラウンドとバックグラウンドにアプリがある場合に、何か処理ができたらありがたいですよね。
例えばバックグラウンドだと、アプリが閉じられてしまったり強制終了した時など、データが保存できず、ユーザーが再度アプリを起動しても今まで操作していた内容や入力内容が消えてしまう可能性があります。
ユーザービリティやUXを考える上でも、入力していたデータが消えてしまったりすると、ユーザーの評価にもつながります。

そのため、バックグラウンド処理など特定のシーンで処理をするための実装について、話そうと思います。

▼ 以下にある。バッググラウンドに行った際の処理が。
参照
@Environment(\.scenePhase) private var scenePhase
これはおまじないで、scenePhaseは予約後で、さらにEnvironmentなので全体の環境変数みたいなもの。
sceneを捕捉していて、Sceneプロトコルを継承して、sceneを捕捉しているので、SceneDelegate的なことができるわけで、
それでアプリがバックグラウンドに行ったらsceneの値が変わるので、@Environmentのバインディングによって処理が走る。
これでバッググラウンドに行った際に.onchange(scenePhase)で検知して処理をする。
scenePhaseには、バックグラウンドに行くとその件数にbaskgroundという値が入る。こういう感じでonchangeが検知する

scenePhaseのさまざまな場合

scenePhase

scenePhase 説明
active シーンはフォアグラウンドでインタラクティブです。
inactive シーンはフォアグラウンドにありますが、作業を一時停止する必要があります。
background シーンは現在UIに表示されていません。

サンプルコード

今までのUI Kitでアプリのライフサイクルを定義していたSceneDelegate.swiftがなくなり、
今後はSwiftUIではEnvironmentで定義することで、バックグラウンド処理を実装できるようになった。

import SwiftUI

@main
struct AppMain: App {
    
    @UIApplicationDelegateAdaptor (AppDelegate.self) var appDelegate
    @Environment(\.scenePhase) private var scenePhase
    
    class AppDelegate: UIResponder, UIApplicationDelegate {
        
            func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
                return true
            }
        }
        
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .onChange(of:scenePhase){phase in
            if phase == .background{
                print(phase)
            } else if phase == .inactive{
                print(phase)
            } else {
                print(phase)
            }
        }
    }
}


struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .padding()
    }
}

@Environment(\.scenePhase) private var scenePhaseを追加。
そしてViewに対して、.onchange配下を追加してます。
.activeで、フォアグラウンドになったらactiveになり、
.backgroundで、バックグラウンドになったらbackgroundになり、
.inactiveで、フォアグラウンドからバックグラウンドになる間で、バックグラウンドからフォアグラウンドになる間で、inactiveになる。

以下で、ビルドした結果を確認してみる。
ビルドしてアプリを起動すると、active
バックグラウンドに移そうとすると、inactiveになって最終的にbackgroundになっている。
そしてまたアプリの画面を開くと、inactiveになってからactiveになっているのが確認できる。

import SwiftUI

@main
struct AppMain: App {
    
    @UIApplicationDelegateAdaptor (AppDelegate.self) var appDelegate
    
    class AppDelegate: UIResponder, UIApplicationDelegate {
        
            func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
                return true
            }
        }
        
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct ContentView: View {
    
    @Environment(\.scenePhase) private var scenePhase
    
    var body: some View {
        TabView{
            Text("Hello, world!")
                .tabItem {
                    Image(systemName: "house")
                    Text("Home").font(/*@START_MENU_TOKEN@*/.largeTitle/*@END_MENU_TOKEN@*/)
                }
            Text("Hello, world2!")
                .tabItem {
                    Image(systemName: "house")
                    Text("Home1").font(/*@START_MENU_TOKEN@*/.largeTitle/*@END_MENU_TOKEN@*/)
                }
                .onChange(of:scenePhase){phase in
                    if phase == .background{
                        print(phase)
                    } else if phase == .inactive{
                        print(phase)
                    } else {
                        print(phase)
                    }
                }
                
        }
    }
}

-IT, アプリ開発
-

© 2022 Yosshi Blog Powered by AFFINGER5