在 SwiftUI 中,如何根据异步调用确定要显示的视图

Posted

技术标签:

【中文标题】在 SwiftUI 中,如何根据异步调用确定要显示的视图【英文标题】:in SwiftUI how do I determine view to show based on async call 【发布时间】:2021-03-14 00:36:27 【问题描述】:

我正在尝试根据异步调用来控制我的应用程序首次出现时的流程,以查看用户是否已登录。

如果这个调用是同步的,我可以做一个简单的 switch 或者 if else 来确定要显示的视图。

但我不知道如何处理基于异步请求的流程。到目前为止,这就是我所做的,但更改状态 var 不会更改显示的视图。以下是app文件中的@main函数:

enum LoginStatus 
    case undetermined
    case signedIn
    case signedOut


@main
struct SignUpApp: App 
    
    @State var loginStatus: LoginStatus = .undetermined
    
    public init() 
        getLoginStatus()
    
    
    var body: some Scene 
        WindowGroup 
            switch loginStatus 
            case .undetermined:
                Text("SigningIn")
            case .signedIn:
                EnterAppView()
            case .signedOut:
                LoginView()
            
        
    
    
    func getLoginStatus() 
        someAsyncFunctionToGetSignInStatus  result in
            DispatchQueue.main.async 
                switch result 
                case .success:
                    self.loginStatus = .signedIn
                case .failure:
                    self.loginStatus = .signedOut
                
            
            
        
    

我想这是一项常见的任务,我想知道处理它的最佳方法是什么。

【问题讨论】:

【参考方案1】:

您的想法是正确的,但通常对于异步调用,您可能希望将它们移动到 ObservableObject 中,而不是将它们放在您的视图代码本身中,因为视图在 SwiftUI 中是瞬态的(尽管例外情况可能是像你一样的***App)。

class SignInManager : ObservableObject 
  @Published var loginStatus: LoginStatus = .undetermined
  
  public init() 
        getLoginStatus()
  

  func getLoginStatus() 
        someAsyncFunctionToGetSignInStatus  result in
            //may need to use DispatchQueue.main.async  to make sure you're on the main thread
            switch result 
            case .success:
                self.loginStatus = .signedIn
            case .failure:
                self.loginStatus = .signedOut
            
        
    
 
@main
struct SignUpApp: App 
    
    @StateObject var signInManager = SignInManager()

    var body: some Scene 
        WindowGroup 
            switch signInManager.loginStatus 
            case .undetermined:
                Text("SigningIn")
            case .signedIn:
                EnterAppView()
            case .signedOut:
                LoginView()
            
        
    

【讨论】:

【参考方案2】:

枚举登录状态 案件未定 案例签到 案例已签出

@main 结构 SignUpApp: 应用程序

@State var loginStatus: LoginStatus = .undetermined

public init() 
    getLoginStatus()


var body: some Scene 
    WindowGroup 
        switch loginStatus 
        case .undetermined:
            Text("SigningIn")
        case .signedIn:
            EnterAppView()
        case .signedOut:
            LoginView()
        
    


func getLoginStatus() 
    someAsyncFunctionToGetSignInStatus  result in
        DispatchQueue.main.async 
            switch result 
            case .success:
                self.loginStatus = .signedIn
            case .failure:
                self.loginStatus = .signedOut
            
        
        
    

【讨论】:

以上是关于在 SwiftUI 中,如何根据异步调用确定要显示的视图的主要内容,如果未能解决你的问题,请参考以下文章

异步firebase调用后SwiftUI不更新变量

如何在 SwiftUI 视图中更新核心数据信息

如何确定在 SwiftUI 中的多词文本视图中点击的词

SwiftUI 中的动画绑定

在asp.net里怎样异步调用WebService方法

如何在 Swiftui 中根据彼此初始化 @State 变量?