Ios 在SwiftUI中更改UIHostingController的根视图
对于新的Ios 在SwiftUI中更改UIHostingController的根视图,ios,swift,swiftui,Ios,Swift,Swiftui,对于新的SwiftUIiOS应用程序,我在SceneDelegate if let windowScene = scene as? UIWindowScene { let window = UIWindow(windowScene: windowScene) if Auth().token == nil { window.rootViewController = UIHostingController(rootView: StartRegistrationView
SwiftUI
iOS应用程序,我在SceneDelegate
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
if Auth().token == nil {
window.rootViewController = UIHostingController(rootView: StartRegistrationView())
} else {
window.rootViewController = UIHostingController(rootView: MainTabbedView())
}
self.window = window
window.makeKeyAndVisible()
}
当用户尚未注册或登录时,他们将进入注册流
用户注册后,如何切换RootView以转到我的选项卡视图?我似乎无法使用SwiftUI
找到任何解决方案
我是否应该改为使用
环境
对象并侦听对用户的身份验证
状态的更改?声明ApprotView,如下所示:
struct AppRootView: View {
@ObservedObject private var auth: Auth
var body: some View {
Group {
if auth.token != nil {
MainTabbedView()
} else {
StartRegistrationView()
}
}
}
}
然后在SceneDelegate中将其设置为根视图:
window.rootViewController=ui宿主控制器(rootView:approtView(auth:$auth))
您必须将视图绑定到Auth(),方法是像我上面所做的那样传入它,或者在您的环境中设置它。SwiftUI的美妙之处在于,只要令牌不是零,视图就会重新绘制,用户就会在MainTabbedView中找到自己。非常好的答案LuLugaga,如果您不想使用@ObservableObject,则会更新,所以不会一直更新,您可以使用Subject,只要您更新令牌字符串,RootView就会更新
struct RootView: View {
var loginViewModel: LoginViewModel = LoginViewModel()
@State var tokenString = ""
var body: some View {
Group {
tokenString.count > 0 ? AnyView(ContentView(model: playerViewModel)) : AnyView(LoginView(loginViewModel: loginViewModel))
}.onReceive(loginViewModel.tokenString) {
self.tokenString = $0
}
}
}
class LoginViewModel {
let tokenString = PassthroughSubject<String, Never>()
var token: String {
get { return "" }
set {
self.tokenString.send(newValue)
}
}
struct RootView:View{
var loginViewModel:loginViewModel=loginViewModel()
@State var tokenString=“”
var body:一些观点{
团体{
tokenString.count>0?任意视图(ContentView(模型:playerViewModel)):任意视图(LoginView(LoginView模型:LoginView模型))
}.onReceive(loginViewModel.tokenString){
self.tokenString=$0
}
}
}
类LoginViewModel{
让tokenString=PassthroughSubject()
变量标记:字符串{
获取{return”“}
设置{
self.tokenString.send(newValue)
}
}
通过使用此选项,我们可以通过实现上述代码在任何按钮单击中更改根视图。对于更改根视图时的一些动画,请在sceneDelegate中使用以下代码:
window.rootViewController = UIHostingController(rootView: HomeView())
// A mask of options indicating how you want to perform the animations.
let options: UIView.AnimationOptions = .transitionCrossDissolve
// The duration of the transition animation, measured in seconds.
let duration: TimeInterval = 0.3
// Creates a transition animation.
UIView.transition(with: window, duration: duration, options: options, animations: {}, completion:
{ completed in
// maybe do something on completion here
})
您可以创建一个路由器类
import Foundation
import UIKit
import SwiftUI
class Router {
class var window: UIWindow? {
if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
if let sceneDelegate = scene.delegate as? SceneDelegate {
let window = UIWindow(windowScene: scene)
sceneDelegate.window = window
window.makeKeyAndVisible()
return window
}
}
return nil
}
static func showMain() {
window?.rootViewController = UIHostingController(rootView: ContentView())
}
}
用法:
Router.showMain()
有了它,您可以在任何给定的时间决定希望哪个窗口作为根用户。在较新的Xcode中,有一些SwiftUI模板更改,下面是如何加载初始视图。请参阅 因此,在本例中,第一个视图是
WelcomeView
,该视图负责导航到正确的视图,可能是login,home
struct WelcomeView: View {
@ObservedObject private var auth = Auth()
var body: some View {
if auth.token != nil {
HomeView()
} else {
SignUpView(auth: auth)
}
}
}
Auth是一个确认ObservableObject
协议的类,具有一个名为token的已发布属性。因此,当此token具有值时,它将在上述情况下加载HomeView
,如果为nil,它将打开SignUpView
class Auth: ObservableObject {
@Published var token: String?
}
struct SignUpView: View {
let auth: Auth
var body: some View {
VStack {
Text("Hello, please click below button to login")
.padding()
Button("Login") {
print("Loogin Tapped")
auth.token = "TOKEN"
}
}
}
}
struct HomeView: View {
var body: some View {
Text("Welcome Parth!")
.padding()
.background(Color.red)
}
}
如果您具有api依赖性并且需要等待令牌,则此方法将非常有用,然后您可以使用
WelcomeScreen
作为一些启动或动画。关于以下方面的任何想法:属性类型“Auth”与其包装类型“ObservedObject”的“wrappedValue”属性的属性不匹配您的Auth类型是否实现了observeObject?Y因此,它必须是一个可观察对象。从今天起,将输出包装到组中会生成编译器警告。相反,我们可以使用类型擦除包装器AnyView
,例如AnyView(MainTabbedView())
(无需组)惊人的方法,但是有没有一种方法可以使这种视图的更改具有动画效果?我自己无法做到。这部分起作用。在应用程序重新启动之前,新视图上的按钮根本没有响应。有没有办法解决此问题?当单击按钮更改rootview控制器时,新视图上的按钮变得没有响应。有没有办法要解决这个问题吗?反应迟钝与此方法无关。我相信这可能是由于按钮的zindex。请尝试更改按钮的索引。“.zindex(1)”
struct WelcomeView: View {
@ObservedObject private var auth = Auth()
var body: some View {
if auth.token != nil {
HomeView()
} else {
SignUpView(auth: auth)
}
}
}
class Auth: ObservableObject {
@Published var token: String?
}
struct SignUpView: View {
let auth: Auth
var body: some View {
VStack {
Text("Hello, please click below button to login")
.padding()
Button("Login") {
print("Loogin Tapped")
auth.token = "TOKEN"
}
}
}
}
struct HomeView: View {
var body: some View {
Text("Welcome Parth!")
.padding()
.background(Color.red)
}
}