当sheet的scenePhase发生变化时触发一个动作。

3

当在一个 sheetscenePhase 发生变化时,如何触发一个动作?我尝试使用 onChange 修饰符,但当应用程序进入后台时它不会触发。

import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .sheet(isPresented: .constant(true), content: SheetView.init)
    }
}

struct SheetView: View {
    @Environment (\.scenePhase) private var scenePhase
    @State private var isFolderLocked = true
    var body: some View {
        Text("Hello, world!")
            .onAppear {
                print("view appeared.")
                // if folder is locked, authenticate and unlock it
            }
            .onChange(of: scenePhase) { newValue in
                print("scenePhase changed.")
                // if scenePhase == .background, lock folder
            }
    }
}

更新后的代码:

import SwiftUI

struct ContentView: View {
    @Environment (\.scenePhase) private var scenePhase
    var body: some View {
        Text("Hello, world!")
            .sheet(isPresented: .constant(true)) {
                SheetView()
                    .environment(\.scenePhase, scenePhase)
            }
    }
}

struct SheetView: View {
    @Environment (\.scenePhase) private var scenePhase
    var body: some View {
        NavigationView {
            NavigationLink("Show FirstDetailsView") {
                FirstDetailsView()
                    .environment(\.scenePhase, scenePhase)
            }
        }
    }
}

struct FirstDetailsView: View {
    @Environment (\.scenePhase) private var scenePhase
    var body: some View {
        NavigationLink("Show SecondDetailsView") {
            SecondDetailsView()
                .environment(\.scenePhase, scenePhase)
        }
        .onChange(of: scenePhase) { _ in
            print("scenePhase changed.")
        }
    }
}

struct SecondDetailsView: View {
    @Environment (\.scenePhase) private var scenePhase
    var body: some View {
        Text("This is SecondDetailsView")
    }
}

似乎 scenePhase 的更改不会传播到 PresentationHostingController,它是 sheet 和其他呈现视图(警报等)的根视图控制器。在我看来,这是一个错误。迄今为止,在所有 iOS 版本中都观察到了这种情况。尽管如此,尚未在 iOS 16 beta 中进行测试。在多个场景中,整个行为都是不稳定的。仅在单个场景中有限使用,因为在这里,问题是可预测的 ;) - CouchDeveloper
1个回答

8
.sheet修饰符引入了新的呈现方式,但是环境不会自动复制到那里。我们必须明确地执行这个操作,例如:
struct ContentView: View {
    @Environment (\.scenePhase) private var scenePhase
    var body: some View {
        Text("Hello, world!")
            .sheet(isPresented: .constant(true)) {
                SheetView()
                  .environment(\.scenePhase, scenePhase)   // << here !!
            }
    }
}

已在 Xcode 13.4 / iOS 15.5 上进行测试。


谢谢,它起作用了,但现在我正在尝试将其实现到我的真实情况中,即ContentView > Sheet > FirstDetailsView > SecondDetailsView。我想观察从FirstSecondView的场景更改,当FirstSecondView在导航堆栈的顶部时,它可以工作,但是当我将SecondDetailsView推到顶部时,FirstSecondView上的观察者停止工作。由于我无法在此处共享代码,因此我将在问题中分享代码。感谢您的帮助。 - Fawzi Rifa'i

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接