我正在开发一个新的社交媒体应用程序,我的导航代码有问题。
一旦用户填写了注册表单,我希望他们被提示上传个人资料图片。我遇到的问题是,它显示了半秒钟的预期视图,然后直接回到注册视图。
我有一个处理UI的RegistrationView和一个负责服务器端通信的AuthViewModel。本质上,当用户完成输入信息并点击按钮时,AuthViewModel接管并将信息发送到firebase,然后触发一个Bool为真。
然后,我在RegistrationView上设置了一个NagivationLink,它侦听该bool,如果为真,则更改UI上的视图。
NavigationLink(destination: ProfilePhotoSelectorView(), isActive: $viewModel.didAuthenticateUser, label:{} )
XCode说它在iOS16中已经过时了,应该转移到他们开发的NavigationStack系统。但是,我看到的每一个指南都不能让它工作。我唯一能让它工作的时间是通过上面的代码,并返回这个UI故障。
下面是RegistrationView的完整代码
import SwiftUI
struct RegistrationView: View {
@State private var email = ""
@State private var username = ""
@State private var fullName = ""
@State private var password = ""
@State private var isVerified = false
@Environment(\.presentationMode) var presentationMode
@EnvironmentObject var viewModel: AuthViewModel
var body: some View {
VStack{
NavigationLink(destination: ProfilePhotoSelectorView(), isActive: $viewModel.didAuthenticateUser, label:{} )
AuthHeaderView(title1: "Get Started.", title2: "Create Your Account.")
VStack(spacing: 40) {
CustomInputFields(imageName: "envelope", placeholderText: "Email", isSecureField: false, text: $email)
CustomInputFields(imageName: "person", placeholderText: "Username", isSecureField: false, text: $username)
CustomInputFields(imageName: "person", placeholderText: "Full Name", isSecureField: false, text: $fullName)
CustomInputFields(imageName: "lock", placeholderText: "Password", isSecureField: true, text: $password)
}
.padding(32)
Button {
viewModel.register(withEmail: email, password: password, fullname: fullName, username: username, isVerified: isVerified)
} label: {
Text("Sign Up")
.font(.headline)
.foregroundColor(.white)
.frame(width: 340, height: 50)
.background(Color("AppGreen"))
.clipShape(Capsule())
.padding()
}
.shadow(color: .gray.opacity(0.5), radius: 10, x:0, y:0)
Spacer()
Button {
presentationMode.wrappedValue.dismiss()
} label: {
HStack {
Text("Already Have And Account?")
.font(.caption)
Text("Sign In")
.font(.footnote)
.fontWeight(.semibold)
}
}
.padding(.bottom, 32)
.foregroundColor(Color("AppGreen"))
}
.ignoresSafeArea()
.preferredColorScheme(.dark)
}
}
struct RegistrationView_Previews: PreviewProvider {
static var previews: some View {
RegistrationView()
}
}
下面是AuthViewModel的完整代码
import SwiftUI
import Firebase
class AuthViewModel: ObservableObject {
@Published var userSession: Firebase.User?
@Published var didAuthenticateUser = false
init() {
self.userSession = Auth.auth().currentUser
print("DEBUG: User session is \(String(describing: self.userSession?.uid))")
}
func login(withEmail email: String, password: String){
Auth.auth().signIn(withEmail: email, password: password) { result, error in
if let error = error {
print("DEBUG: Failed to sign in with error\(error.localizedDescription)")
return
}
guard let user = result?.user else { return }
self.userSession = user
print("Did log user in")
}
}
func register(withEmail email: String, password: String, fullname: String, username: String, isVerified: Bool){
Auth.auth().createUser(withEmail: email, password: password) { result, error in
if let error = error {
print("DEBUG: Failed to register with error\(error.localizedDescription)")
return
}
guard let user = result?.user else { return }
print("DEBUG: Registerd User Succesfully")
let data = ["email": email, "username" :username.lowercased(), "fullname": fullname, "isVerified": isVerified, "uid": user.uid]
Firestore.firestore().collection("users")
.document(user.uid)
.setData(data) { _ in
self.didAuthenticateUser = true
}
}
}
func signOut() {
userSession = nil
try? Auth.auth().signOut()
}
}
下面是ProfilePhotoSelectorView的代码
import SwiftUI
struct ProfilePhotoSelectorView: View {
var body: some View {
VStack {
AuthHeaderView(title1: "Account Creation:", title2: "Add A Profile Picture")
Button {
print("Pick Photo Here")
} label: {
VStack{
Image("PhotoIcon")
.resizable()
.renderingMode(.template)
.frame(width: 180, height: 180)
.scaledToFill()
.padding(.top, 44)
.foregroundColor(Color("AppGreen"))
Text("Tap To Add Photo")
.font(.title3).bold()
.padding(.top, 10)
.foregroundColor(Color("AppGreen"))
}
}
Spacer()
}
.ignoresSafeArea()
.preferredColorScheme(.dark)
}
}
struct ProfilePhotoSelectorView_Previews: PreviewProvider {
static var previews: some View {
ProfilePhotoSelectorView()
}
}
尝试了新NavigationStack的所有变体,并尝试了一些其他按钮代码,看看我是否可以从那里触发它。没有Reso
3条答案
按热度按时间xn1cxnb41#
不推荐以这种方式使用
NavigationLink
,所以我并不奇怪它会导致错误的行为。这是由于您的RegistrationView
没有放在NavigationView
(已弃用)或NavigationStack
中,因为这些视图提供了导航链接的大部分功能。就像你说的,
NavigationLink
的这种用法已经过时了。在我看来,isActive
属性一直有点模棱两可(据我所知,它并不是导航链接的“激活器”,而是一种读取链接是否活动的方式)。显示导航链接的新方式(使用.navigationDestination
)要好得多。使用布尔属性显示视图
实际上,你需要的是当一个布尔属性被切换为true时,显示
ProfilePhotoSelectorView
。这是SwiftUi中的常见范例,有很多方法可以实现这一点,比如.sheet(isPresented:content:)
或.popover(isPresented:content:)
。注意,这两个方法中的isPresented
参数都是布尔属性。例如,使用.sheet
:向导航树添加新视图
如果您坚持使用导航链接(也就是说,您 * 真的 * 希望
ProfilePhotoSelectorView
成为导航树中的一个节点),那么您必须学习使用新的NavigationStack
并将视图追加到路径上。here和here是一个很好的起点)视图模型是最有可能控制堆栈的地方,尽管你最终可能想创建一个专用的视图模型。pdsfdshx2#
如果我没理解错你的问题,你想使用
NavigationStack
,但它不适合你。这里有许多遗漏的部分,但这里是我尝试使用
NavigationStack
来触发目的地,假定viewModel.didAuthenticateUser
发生了变化。holgip5t3#
除非将链接标记为
isDetail(false)
或使用.navigationStyle(.stack)
,否则只能有一个NavigationLink
级别。这是因为在横向模式下,它使用拆分视图,并且链接取代了右侧的大细节窗格。