我正在尝试执行一些我之前放在我的应用程序委托中的代码,例如在进入后台时保存我的托管对象上下文。我将调用放入了.onChangeScenePhase,但我什么也没收到。这是一个示例项目:
import SwiftUI
@main
struct PhaseApp: App {
@Environment(\.scenePhase) private var scenePhase
var body: some Scene {
WindowGroup {
Text("Hello, world.")
}
.onChange(of: scenePhase) { phase in
switch phase {
case .active:
print("Active")
case .background:
print("Background")
case .inactive:
print("Inactive")
@unknown default: break
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
每当我按 Home 或点击应用程序时,我都希望在模拟器或我的测试设备上收到打印命令,但没有任何反应。
Par*_*tra 31
我承认这个问题专门与更改有关,但是,在 macOS 上,当用户切换到其他应用程序时,schenePhase我无法收到任何通知。.background旧NotificationCenter策略在两个平台上都按我的预期运行。我会将其添加到任何只是尝试执行某些代码onForeground/onBackground和iOS的人的组合中macOS。
在任何视图上,您都可以附加:
.onReceive(NotificationCenter.default.publisher(for: .willResignActiveNotification)) { _ in
doBackgroundThing()
}
Run Code Online (Sandbox Code Playgroud)
您可能关心的事件有:
willResignActiveNotification&willEnterForegroundNotificationwillResignActiveNotification&willBecomeActiveNotification 您可以在这里找到所有NotificationCenter Name内容。
我使用will*变体作为后台,因为我假设它们会在流程的早期被调用,并且我使用did*变体作为前台,因为无论应用程序是第一次启动还是从后台出来,它们都会被调用。
我使用这个扩展,所以我不必考虑平台差异:
extension View {
#if os(iOS)
func onBackground(_ f: @escaping () -> Void) -> some View {
self.onReceive(
NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification),
perform: { _ in f() }
)
}
func onForeground(_ f: @escaping () -> Void) -> some View {
self.onReceive(
NotificationCenter.default.publisher(for: UIApplication.didBecomeActiveNotification),
perform: { _ in f() }
)
}
#else
func onBackground(_ f: @escaping () -> Void) -> some View {
self.onReceive(
NotificationCenter.default.publisher(for: NSApplication.willResignActiveNotification),
perform: { _ in f() }
)
}
func onForeground(_ f: @escaping () -> Void) -> some View {
self.onReceive(
NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification),
perform: { _ in f() }
)
}
#endif
}
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,我这样使用它:
AppView()
.onBackground {
print("my background")
}
.onForeground {
print("my foreground")
}
Run Code Online (Sandbox Code Playgroud)
Asp*_*eri 10
使用内部场景根视图(通常ContentView)
已使用 Xcode 12 / iOS 14 进行测试。
struct ContentView: View {
@Environment(\.scenePhase) private var scenePhase
var body: some View {
TestView()
.onChange(of: scenePhase) { phase in
switch phase {
case .active:
print(">> your code is here on scene become active")
case .inactive:
print(">> your code is here on scene become inactive")
case .background:
print(">> your code is here on scene go background")
default:
print(">> do something else in future")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我一直在使用 Xcode 12 beta 3 和 iOS/iPadOS 14 beta 3 进行测试,这就是我的发现。请注意,其中很多涉及支持多个窗口,但“SwiftUI 生命周期”项目默认将其打开,因此我怀疑您已经将其激活。在我最初的情况下,我将现有的 SwiftUI 应用程序从 a 移植SceneDelegate到使用新App结构,因此我已经激活了多个窗口支持。
这是View我在新测试应用程序中使用的测试:
struct ContentView: View {
@Environment(\.scenePhase) private var scenePhase
var body: some View {
Text("Hello, world!").padding()
.onChange(of: scenePhase) { phase in
switch phase {
case .background:
print("PHASECHANGE: View entered background")
case .active:
print("PHASECHANGE: View entered active")
case .inactive:
print("PHASECHANGE: View entered inactive")
@unknown default:
print("PHASECHANGE: View entered unknown phase.")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
(我在App& 中有相同的代码,Scene但它们从不打印任何内容。)
该ScenePhase文档声称,你可以声明onChange内App,一个Scene 或一个View。在我可以设计的任何情况下,我都没有看到App或Scene级别版本执行,并且View级别版本似乎没有完全正确执行。
在不支持多窗口的硬件上(我使用第 7 代 iPod touch),每次都会 编辑(它确实很重要。)在运行不支持多窗口(第 7 代 iPod Touch)的 beta 2 的硬件上,我看到应用程序进入后台,回到前台,等等。在每次应用程序启动时,我都会看到“查看已输入活动”打印。View执行关卡关闭。(完全披露,这款 iPod Touch 仍在运行 beta 2,但我认为这无关紧要。一旦我将其更新为 b3,我会在此处提及它(如果重要的话)。)
在硬件不支持多窗口(我用一个旧的iPad临用闪电接口)我没有看到初始场景创建发生。(第一次运行并没有触发“视图进入活跃”的消息。)我确实看到后续的背景/前景的转变。如果我从 iPad 多任务用户界面创建一个新场景,第二个场景将触发“视图输入活动”日志。不幸的是,我没有在 iPad 上针对 beta 2 运行此测试,所以我不能说行为是否随 b3 改变。
在运行 iOS 14 beta 3 的 iPod Touch 上,我看到与 iPad 相同的行为:第一次启动不会从视图打印任何相变消息,但会报告后续的背景/前景变化。
在模拟器上,它总是表现得像 iPad 硬件,即使我在模拟 iPod Touch。我怀疑这是因为模拟器在 Mac 上运行在引擎盖下,并以这种方式获得多窗口“支持”。但是,当我在模拟器中运行时将应用程序置于后台时,我确实看到了消息,我只是错过了从实际硬件获得的初始“查看已输入活动”消息。
最后一个注意事项:当我从前台返回一个应用程序时,我首先看到“视图进入非活动状态”,然后我看到“视图进入活动状态”。当我后台应用程序时,我看到“查看进入非活动状态”,然后是“查看进入的背景”。我认为这是预期的行为,但由于其他部分似乎已损坏,我想提一下。
特尔;博士:
我认为您应该能够看到 a 的大部分 ScenePhase更改View,但您会错过最初的应用程序启动在 iPad 上或在模拟器中. 并且希望它们会在以后的测试版中按预期显示App和Scene对象?
| 归档时间: |
|
| 查看次数: |
1692 次 |
| 最近记录: |