如何在 SwiftUI 中启动应用程序时有条件地加载视图?

Posted

技术标签:

【中文标题】如何在 SwiftUI 中启动应用程序时有条件地加载视图?【英文标题】:How to conditionally load view upon app launch in SwiftUI? 【发布时间】:2021-04-13 22:29:06 【问题描述】:

我目前正在尝试使用 UserDefaults 为我的应用程序实现自动登录功能。在加载任何视图之前,我想做的是获取 UserDefaults 电子邮件和密码,并从我的 API 调用登录函数。如果成功,转到 Home 视图,否则转到 LoginView。抱歉,我对 Swift 很陌生,而且我的项目时间紧迫。这是我的代码段。我不确定在哪里可以添加我的逻辑:

import SwiftUI

@main
struct MyApp: App 
    init() 
        let email = UserDefaults.standard.string(forKey: "email");
        let pw = UserDefaults.standard.string(forKey: "pw");
        
        let api = MyAppAPI()
        api.signInUser(email: email, password: pw)  result in
            //JSON response contains an 'isError' field
            let isError = result.value(forKey: "error") as! Bool
            
            if !isError 
                //successful login - what to do from here?   
            
        
    
    
    var body: some Scene 
        WindowGroup 
            LoginView()
        
    

【问题讨论】:

我建议不要在您成功进行网络呼叫之前暂停应用启动。我会将用户启动到某种加载/瞬态屏幕,然后在解析网络调用后将它们导航到适当的屏幕。例如,如果这是一个需要网络连接的银行应用程序,那么这绝对是我的选择。但是,例如,如果这是一个社交网络应用程序,那么我会避免这种方法,并尝试使用户体验尽可能离线,即使在没有连接的情况下也能在一定程度上工作。 需要网络连接就足够了。这是一个为期一学期的项目,我必须学习 Swift、php 和 AWS。离线使用此应用程序确实没有任何目的。我想可以缓存一些信息,但这超出了这个项目的范围和我的经验水平 【参考方案1】:

这是一个简单的方法,你可以这样做onAppear


import SwiftUI

struct ContentView: View 
    
    let email: String
    let pass: String

    init() 
        self.email = UserDefaults.standard.string(forKey: "email") ?? ""
        self.pass = UserDefaults.standard.string(forKey: "pw") ?? ""
    
    
    @State private var result: Bool?

    var body: some View 
        
        Group 
            
            if let unwrappedResult: Bool = result 
                
                if unwrappedResult 
                    
                    Text("Home View, Welcome!")
                
                else 
                    
                    Text("Wrong User or Pass, try again!")
                
                
            
            else 
                
                Text("loading...")
                
            
  
        
        .onAppear()  loginFunction(email: email, pass: pass)  value in result = value  

    


func loginFunction(email: String, pass: String, completion: @escaping (Bool) -> Void) 

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.milliseconds(3000))  completion(Bool.random()) 
  

【讨论】:

感谢分享。我会试一试这种方法 除了 1 个奇怪的问题外,您的示例运行良好。我的应用程序目前有一个启动屏幕。我从 Info.plist 中删除了它,并将图像放在最后一个 else 块中作为我的新启动屏幕。现在每当我启动应用程序时,整个应用程序窗口都非常小,有点像在只支持 iPhone 屏幕的 iPad 上运行应用程序。如果我将启动屏幕保留在 Info.plist 中,一切都是完美的,但显然没有必要让启动屏幕只是为了转到具有相同图像的视图。有什么想法吗? 那个听起来很不同的问题和不同的问题,如果你愿意,你可以提出一个新的问题,但对于当前的问题,我认为我们已经完成了。 想通了。出于某种原因,当没有启动屏幕时会发生这种情况,所以在转到此视图之前,我基本上只是有一个空白的启动屏幕(***.com/questions/63195985/…)。感谢您提供非常有用的 ContentView 示例! @nickconnors:请不要将您的问题与新问题混为一谈,以便在您的下一个问题中获得新答案,您最初的问题是:如何在 SwiftUI 中启动应用时有条件地加载视图?你没有提到启动屏幕,我什至没有尝试回答启动屏幕问题!我知道你是 SOF 的新手,但请只问一个问题并停留在一个问题上,不要到时候改变问题。 ps:我的回答曾经是并且现在是针对您的原始问题,我认为这是一个很好的答案示例。

以上是关于如何在 SwiftUI 中启动应用程序时有条件地加载视图?的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI:动画列表中的圆圈

如何检测手表操作系统是不是关闭了 ios 应用程序 SWIFTUI

如何使用 .NET Core 安全地加/解密文件 #yyds干货盘点#

SWIFTUI:在视图中导航并返回

如何在视图启动之前在 SwiftUI 中加载更新的变量?

SwiftUI 如何根据条件导航到多个可能的视图?