使用 SceneDelegate.toView() 弹出视图

Posted

技术标签:

【中文标题】使用 SceneDelegate.toView() 弹出视图【英文标题】:Popping views using SceneDelegate.toView() 【发布时间】:2020-12-12 13:31:20 【问题描述】:

我有一个 UI,您可以在其中导航/推送视图,如下所示: AView -> BView -> CView -> DView

我想弹出几个视图(从 DView 到 BView),而不是在现有堆栈顶部放置一个新视图 (BView),我找到了这样做的方法:

(UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.toBView()

我不明白的是,当我尝试从 DView 返回到 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)
    


【问题讨论】:

【参考方案1】:

这种行为没有错。如果您启动您的应用并显示 AView,您将在控制台中看到它从 A 和 B 打印 init。

这是因为 BView() 已经在您的 AView 中初始化,即使您还没有激活 NavigationLink。

NavigationLink(destination: BView()) 

因此,此行为并非特定于您的弹回操作,而是在开始时已经发生。如果您担心多次调用 init(),请参阅 Asperi 的 this 解决方案关于多个 init() 的问题

【讨论】:

以上是关于使用 SceneDelegate.toView() 弹出视图的主要内容,如果未能解决你的问题,请参考以下文章

第一篇 用于测试使用

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份