我正在尝试执行一些我以前放到我的应用程序委托中的代码,例如在进入后台时保存我的托管对象上下文。我已将呼叫放入场景阶段的.onChange
中,但没有收到任何信息。这是一个示例项目:
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
}
}
}
}
我希望每当我按Home或点击应用程序时,都会在模拟器或测试设备上获得打印命令,但是什么也没发生。
答案 0 :(得分:5)
使用内部场景根视图(通常为#include <stdio.h>
int main()
{
char a[1000] = {0};
float L;
int flag;
//read a line from input
printf("Text:");
scanf("%[^\n]s", a);
float word_count = 0;
float letter_count = 0;
int sent_count = 0;
int idx = 0;
// go through the line
while (a[idx]){
// if next char is special char, then we found a sentence
if(a[idx] == '.' || a[idx] == '?' || a[idx] == '!' || a[idx] == '\n')
{
sent_count++;
idx++;
}
//skip spaces
while(a[idx] && isspace(a[idx]))
idx++;
// if next char is a letter => we found a word
/* if (a[idx])
word_count++;*/
flag =0;
//skip the word, increment number of letters
while(a[idx] && !isspace(a[idx]) && a[idx]!='.' && a[idx]!='?' && a[idx]!='!' && a[idx]!='\n'){
letter_count++;
idx++;
flag =1;
}
if(flag ==1 )
word_count++;
}
printf("word count = %f\nletter count = %f\n", word_count, letter_count);
L = letter_count/word_count*100;
printf("L= %.2f\n", L);
printf("# of Sentences: %d\n", sent_count);
}
)
在Xcode 12 / iOS 14上进行了测试。
ContentView
答案 1 :(得分:3)
我一直在使用Xcode 12 beta 3和iOS / iPadOS 14 beta 3进行测试,这就是我所发现的。请注意,其中很多涉及支持多个窗口,但是“ SwiftUI生命周期”将 default 项目设置为启用该窗口,因此我怀疑您已将其激活。在我的原始情况下,我将现有的SwiftUI应用从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.")
}
}
}
}
(我在App
和Scene
中使用相同的代码,但它们从不打印任何内容。)
ScenePhase documentation声称您可以在onChange
,App
或 Scene
中声明View
。在我可以设计的任何情况下,我都没有看到App
或Scene
级别的版本能够执行,并且View
级别的版本似乎不能完全正确地执行。
在不支持多个窗口的硬件上(我使用的是第七代iPod touch), 编辑< / strong>(这很重要。)
在运行不支持多个窗口的beta 2的硬件(第7代iPod Touch)上,我看到该应用程序进入后台,回到前台,依此类推。每次启动应用程序时,我都会看到“查看已输入有效”的打印内容。View
级闭包会每执行一次 时间。 (完整披露,此iPod Touch仍在运行beta 2,但我认为这无关紧要。一旦将其更新为b3,就可以在这里提及它。)
在支持 的硬件上(我使用带有Lightning接口的较旧的iPad Pro)我看不到最初的场景创建。 (第一次运行不会 not 触发“查看输入激活”消息。)我确实看到了后续的背景/前景转换。如果我从iPad多任务UI创建新场景,则 second 场景将触发“查看输入的活动”日志。不幸的是,我没有针对beta 2在iPad上运行此测试,因此我无法确定行为是否随b3改变。
在运行iOS 14 beta 3的iPod Touch上,我看到的行为与iPad相同:第一次启动不会从视图中打印任何相变消息,但是会报告随后的背景/前景更改。>
在模拟器上,即使我正在模拟iPod Touch,它的行为也始终像iPad硬件一样。我怀疑这是因为模拟器在Mac的引擎盖下运行,并且以这种方式获得了多个窗口“支持”。但是,当我在模拟器中运行该应用程序并置于后台时,我确实看到了消息,但我只是缺少了从实际硬件中获得的初始“查看输入的活动”消息。
最后一点:当我从前台退回一个应用程序时,我先看到“输入的视图无效”,然后看到“输入的视图有效”。当我后台应用程序时,我看到“查看输入的背景不活跃”,然后显示“查看输入的背景”。我认为这是预期的行为,但由于其他部分似乎已损坏,因此我想提一下。
TL; DR:
我认为您应该可以看到{em {em}} {em {em}} ScenePhase
的变化,但是您会错过iPad或iPad上最初启动的应用程序。模拟器。希望它们会在以后的Beta版中按预期显示给View
和App
对象吗?
答案 2 :(得分:0)
您可以使用以下扩展名:
public extension View {
func OnScenePhaseChange(phase: ScenePhase, action: @escaping () -> ()) -> some View
{
self.modifier( OnScenePhaseChangeModifier(phase: phase, action: action) )
}
}
public struct OnScenePhaseChangeModifier: ViewModifier {
@Environment(\.scenePhase) private var scenePhase
public let phase: ScenePhase
public let action: () -> ()
public func body(content: Content) -> some View {
content
.onChange(of: scenePhase) { phase in
if (phase == phase) {
action()
}
}
}
}
最终用法:
ContentView()
.OnScenePhaseChange(phase: .active) { print("scene activated!") }
.OnScenePhaseChange(phase: .background) { print("scene backgrounded!") }
.OnScenePhaseChange(phase: .inactive) { print("scene inactive!") }