[英]How to transition Views programmatically using SwiftUI?
我想在登錄成功時向用戶顯示另一個視圖,否則留在該視圖上。 我已經通過執行轉場使用 UIKit 做到了這一點。 SwiftUI 中有這樣的選擇嗎?
NavigationButton 解決方案不起作用,因為我需要在轉換到另一個視圖之前驗證用戶輸入。
Button(action: {
let authService = AuthorizationService()
let result = authService.isAuthorized(username: self.username, password: self.password)
if(result == true) {
print("Login successful.")
// TODO: ADD LOGIC
*** HERE I WANT TO PERFORM THE SEGUE ***
presentation(MainView)
} else {
print("Login failed.")
}
}) {
Text("Login")
}
Xcode 11 測試版 5。
NavigationDestinationLink
和NavigationButton
已被棄用並由NavigationLink
取代。
這是以編程方式將視圖推送到 NavigationView 的完整工作示例。
import SwiftUI
import Combine
enum MyAppPage {
case Menu
case SecondPage
}
final class MyAppEnvironmentData: ObservableObject {
@Published var currentPage : MyAppPage? = .Menu
}
struct NavigationTest: View {
var body: some View {
NavigationView {
PageOne()
}
}
}
struct PageOne: View {
@EnvironmentObject var env : MyAppEnvironmentData
var body: some View {
let navlink = NavigationLink(destination: PageTwo(),
tag: .SecondPage,
selection: $env.currentPage,
label: { EmptyView() })
return VStack {
Text("Page One").font(.largeTitle).padding()
navlink
.frame(width:0, height:0)
Button("Button") {
self.env.currentPage = .SecondPage
}
.padding()
.border(Color.primary)
}
}
}
struct PageTwo: View {
@EnvironmentObject var env : MyAppEnvironmentData
var body: some View {
VStack {
Text("Page Two").font(.largeTitle).padding()
Text("Go Back")
.padding()
.border(Color.primary)
.onTapGesture {
self.env.currentPage = .Menu
}
}.navigationBarBackButtonHidden(true)
}
}
#if DEBUG
struct NavigationTest_Previews: PreviewProvider {
static var previews: some View {
NavigationTest().environmentObject(MyAppEnvironmentData())
}
}
#endif
請注意, NavigationLink
實體必須存在於視圖主體內。 如果您有觸發鏈接的按鈕,您將使用 NavigationLink 的標簽。 在這種情況下,NavigationLink 通過將其框架設置為 0,0 來隱藏,這是一種黑客行為,但我目前不知道更好的方法。 .hidden() 沒有同樣的效果。
根據此響應,您可以像下面那樣做(它像 Playground 一樣打包以便於測試:
import SwiftUI
import Combine
import PlaygroundSupport
struct ContentView: View {
var body: some View {
NavigationView {
MainView().navigationBarTitle(Text("Main View"))
}
}
}
struct MainView: View {
let afterLoginView = DynamicNavigationDestinationLink(id: \String.self) { message in
AfterLoginView(msg: message)
}
var body: some View {
Button(action: {
print("Do the login logic here")
self.afterLoginView.presentedData?.value = "Login successful"
}) {
Text("Login")
}
}
}
struct AfterLoginView: View {
let msg: String
var body: some View {
Text(msg)
}
}
PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())
雖然這會奏效,但我認為,從架構的角度來看,您嘗試將“命令式編程”范式推入 SwiftUI 的響應式邏輯中。 我的意思是,我寧願將登錄邏輯封裝到ObjectBinding
類中,並帶有公開的isLoggedin
屬性來實現它,並使 UI 對當前狀態(由isLoggedin
表示)做出反應。
這是一個非常高級的示例:
struct MainView: View {
@ObjectBinding private var loginManager = LoginManager()
var body: some View {
if loginManager.isLoggedin {
Text("After login content")
} else {
Button(action: {
self.loginManager.login()
}) {
Text("Login")
}
}
}
}
我使用 Bool 狀態進行登錄轉換,它看起來非常流暢。
struct ContentView: View {
@State var loggedIn = false
var body: some View {
VStack{
if self.loggedIn {
Text("LoggedIn")
Button(action: {
self.loggedIn = false
}) {
Text("Log out")
}
} else {
LoginPage(loggedIn: $loggedIn)
}
}
}
}
也可以通過編程方式完成,例如:
let vc = self.storyboard?.instantiateViewController(withIdentifier: "TheTargetViewController")
self.present(vc!, animated: true, completion: nil)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.