Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Authentication 快速确定初始视图_Authentication_Push Notification_Swiftui - Fatal编程技术网

Authentication 快速确定初始视图

Authentication 快速确定初始视图,authentication,push-notification,swiftui,Authentication,Push Notification,Swiftui,我正在尝试在SwiftUI生命周期中制作的应用程序的开始部分找到导航。根据启动时确定的设置,用户可以在三个视图中的一个视图中启动。如果用户通过推送通知打开应用程序,他们应该会看到视频视图(WrappedVideoViewController)。否则,如果他们已经登录,他们应该会看到主视图,如果没有,则会看到登录视图。我使用ContentView作为父级: import SwiftUI struct ContentView: View { @EnvironmentObject var n

我正在尝试在SwiftUI生命周期中制作的应用程序的开始部分找到导航。根据启动时确定的设置,用户可以在三个视图中的一个视图中启动。如果用户通过推送通知打开应用程序,他们应该会看到视频视图(WrappedVideoViewController)。否则,如果他们已经登录,他们应该会看到主视图,如果没有,则会看到登录视图。我使用ContentView作为父级:

import SwiftUI

struct ContentView: View {
    @EnvironmentObject var notifService: NotificationService
    @EnvironmentObject var authState: AuthenticationState
    
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
        
    @ObservedObject var viewRouter: ViewRouter
    
    init() {
        self.viewRouter = ViewRouter.shared
    }
    
    var body: some View {
        
        print("in ContentView body")
        
        switch viewRouter.currentScreen {
        case .home:
            print("home")
            return AnyView(Home(innerGradientColor: Color.homeActiveInner, outerGradientColor: Color.homeActiveOuter))
        case .login:
            print("login")
            return
                AnyView(Login()
                .environmentObject(AuthenticationState.shared))
        case .video:
            print("video")
            return AnyView(WrappedVideoViewController())

        }
            
    }

}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
            .environmentObject(AuthenticationState.shared)
            .environmentObject(NotificationService())
    }
}
我的ViewRouter类是一个ObserveObject,用于控制显示哪个屏幕。目前,我有:

//
//  NavigationState.swift
//  BumpCall-SwiftUI
//
//  Created by Ben on 1/22/21.
//

import Foundation
import SwiftUI

enum Screen {
    case home
    case video
    case login
}

class ViewRouter: ObservableObject {
    
    var authState: AuthenticationState
    var notifService: NotificationService
    
    static var shared = ViewRouter(authState: AuthenticationState.shared, notifService: NotificationService.shared)
    
    init(authState: AuthenticationState, notifService: NotificationService) {
        self.authState = authState
        self.notifService = notifService
        
        if notifService.dumbData != nil {
            currentScreen = .video
        } else if (notifService.dumbData == nil && authState.isLoggedIn()) {
            currentScreen = .home
        } else {
            currentScreen = .login
        }
        
    }
    
    @Published var currentScreen: Screen
    
}
这很棘手,因为ViewRouter依赖于另外两个ObserveObject,我在这里试图用init()处理它们。AuthenticationState类似乎工作正常,因为在打开应用程序时,如果您登录,它会将您发送到主屏幕。但是,从通知打开也会将我发送到主屏幕。NotificationService更改didReceive响应中的ViewRouter单例:方法:

class NotificationService: NSObject, ObservableObject {
    @Published var dumbData: UNNotificationResponse?
    
    static var shared = NotificationService()
    
    override init() {
        super.init()
        UNUserNotificationCenter.current().delegate = self
    }
}

extension NotificationService: UNUserNotificationCenterDelegate  {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        print("presenting notification")
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        ViewRouter.shared.notifService.dumbData = response
        print("Notification service didReceive response")
        completionHandler()
    }

    func userNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification?) { }
    
}

但是单例不能更新,ContentView才会注意到。这是一个非常复杂的问题,让我困惑了好几天,任何帮助都将不胜感激。

问题是
ViewRouter
init()
将被调用一次。如您所述,当用户登录时,
currentScreen
将被初始化为
.home
。但是,此变量以后将永远不会更改

您基本上想要的是在通知委托内将
currentScreen
设置为
.video

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    ViewRouter.shared.currentScreen = .video //<< here set video 
    print("Notification service didReceive response")
    completionHandler()
}
func userNotificationCenter(center:UNUserNotificationCenter,didReceive响应:UNNotificationResponse,withCompletionHandler completionHandler:@escaping()->Void){

ViewRouter.shared.currentScreen=.video//非常感谢您,这非常好用。