使用 SceneDelegate.toView() 弹出视图
Popping views using SceneDelegate.toView()
我有一个 UI,您可以在其中 navigate/push 查看如下内容:
AView -> BView -> CView -> DView
我想弹出几个视图(从 DView 到 BView)而不是在现有堆栈顶部放置一个新视图 (BView),我找到了执行此操作的方法:
(UIApplication.shared.connectedScenes.first?.delegate as?
SceneDelegate)?.toBView()
我不明白的是,当我尝试从 DView return 到 BView 时,为什么它会调用 CView 的 init()?
这是我在调试控制台中得到的输出:
AView init
BView init
CView init
DView init
contract.
button pressed
BView init
**CView init**
为什么它会调用 CView 的 init() 以及如何避免这种行为?
AView.swift:
import SwiftUI
struct AView: View {
init() {
print("AView init")
}
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: BView()) {
Text("This is View A, now go to View B.")
}
}
}
}
}
struct BView: View {
init() {
print("BView init")
}
var body: some View {
NavigationLink(destination: CView()) {
Text("This is View B, now go to View C.")
}
}
}
struct CView: View {
init() {
print("CView init")
}
var body: some View {
NavigationLink(destination: DView()) {
Text("This is View C, now go to View D.")
}
}
}
struct DView: View {
init() {
print("DView init")
}
var body: some View {
Button(action: {
print("button pressed")
(UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.toBView()
},
label: {
Text("Back!")
})
}
}
SceneDelegate.swift:
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Create the SwiftUI view that provides the window contents.
let aView = AView()
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: AView)
self.window = window
window.makeKeyAndVisible()
}
}
func toBView() {
let bView = BView()
window?.rootViewController = UIHostingController(rootView: bView)
}
}
这种行为并没有错。如果您启动您的应用程序并显示 AView,您将在控制台中看到它从 A 和 B 打印 init。
这是因为 BView() 已经在您的 AView 中初始化,即使您还没有激活 NavigationLink。
NavigationLink(destination: BView()) {
因此,此行为并非特定于您的弹回操作,它在一开始就已经发生了。如果您担心多次调用 init() ,请参阅 Asperi 关于多个 init() 的解决方案
我有一个 UI,您可以在其中 navigate/push 查看如下内容: AView -> BView -> CView -> DView
我想弹出几个视图(从 DView 到 BView)而不是在现有堆栈顶部放置一个新视图 (BView),我找到了执行此操作的方法:
(UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.toBView()
我不明白的是,当我尝试从 DView return 到 BView 时,为什么它会调用 CView 的 init()?
这是我在调试控制台中得到的输出:
AView init
BView init
CView init
DView init
contract.
button pressed
BView init
**CView init**
为什么它会调用 CView 的 init() 以及如何避免这种行为?
AView.swift:
import SwiftUI
struct AView: View {
init() {
print("AView init")
}
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: BView()) {
Text("This is View A, now go to View B.")
}
}
}
}
}
struct BView: View {
init() {
print("BView init")
}
var body: some View {
NavigationLink(destination: CView()) {
Text("This is View B, now go to View C.")
}
}
}
struct CView: View {
init() {
print("CView init")
}
var body: some View {
NavigationLink(destination: DView()) {
Text("This is View C, now go to View D.")
}
}
}
struct DView: View {
init() {
print("DView init")
}
var body: some View {
Button(action: {
print("button pressed")
(UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.toBView()
},
label: {
Text("Back!")
})
}
}
SceneDelegate.swift:
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Create the SwiftUI view that provides the window contents.
let aView = AView()
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: AView)
self.window = window
window.makeKeyAndVisible()
}
}
func toBView() {
let bView = BView()
window?.rootViewController = UIHostingController(rootView: bView)
}
}
这种行为并没有错。如果您启动您的应用程序并显示 AView,您将在控制台中看到它从 A 和 B 打印 init。
这是因为 BView() 已经在您的 AView 中初始化,即使您还没有激活 NavigationLink。
NavigationLink(destination: BView()) {
因此,此行为并非特定于您的弹回操作,它在一开始就已经发生了。如果您担心多次调用 init() ,请参阅