【问题标题】:How to access a View Struct in other View struct in swiftui如何在swiftui中访问其他视图结构中的视图结构
【发布时间】:2020-11-15 21:25:02
【问题描述】:

在一个视图中,我有这个函数来注册并获取用户名

func signUp() {
 
    if self.email != "" {
        if self.password == self.repass {
    session.signUp(email: email, password: password) { (result, error) in
        
        if error != nil {
            self.error = error!.localizedDescription
            //self.error = "A senha deve ter 6 caracteres ou mais"
        }
            else{
                self.email = ""
                self.password = ""
                
                let db = Firestore.firestore()
                db.collection("Users").document(result!.user.uid).setData(["userName": userName]) { (error) in
                    if error != nil{
                    
                    }
                }
                
            }
        }
    }
        else{
            self.error = "Senhas não coincidem"
        }
}
    else{
        self.error = "Complete todos espaços"
}
}

在其他视图中,我想获取用户键入的广告显示它的用户名,但为此我需要链接两个视图以访问 func SignUp。怎么做?

编辑:

根据我给出的答案,我做了相应的修改:

会话存储:

@Published var session: User? = nil
var handle: AuthStateDidChangeListenerHandle?
@Published var userName: String = ""




func listen() {
    
    handle = Auth.auth().addStateDidChangeListener({ [self] (auth, user) in
        if let user = user {
            self.session = User(uid: user.uid, email: user.email!, userName: userName)
        }
        else {
            self.session = nil
        }
    })
}




struct User {

var uid:String
var email:String
var userName: String

}

HomeView ----> var userName: User

Text(userName.userName)
  • 解释我的代码是如何工作的:@main 视图是MedAppApp: App。从那里,代码转到ContentView。如果session.session != nilTransitionView,否则,SignView。从SignView 开始,我同时拥有SignInViewSignUpView 视图,它们分别拥有Button(action: signIn)Button(action: Signup)。继续TransitionView,我有:

     struct TransitionView: View {
     @StateObject var LocationModel = LocationViewModel()
     @State var userName = User(uid: "", email: "", userName: "")
    
     var body: some View {
         HomeView(LocationModel: LocationModel, userName: userName)
     }
    }
    
  • 需要添加@State var userName =...userName: userName

应用启动后,我可以使用用户名注册(并将其以 uid 作为文档存储在 Firestore 中),但未显示用户名。我认为问题一定出在用户(uid:“”,电子邮件:“”,密码:“”)。我不知道要在那里添加什么。

顺便说一句,我正在考虑维护代码,然后通过使用文档 id(已经是用户 uid)获取用户名,以便我可以访问它。目前还没有最终答案,但我正在努力。

EDIT2: 我添加了@StateObject var session = SessionStore()

尝试使用:

@State var userName = User(uid: SessionStore().session?.uid ?? "", email: SessionStore().session?.email ?? "", userName: SessionStore().session?.userName ?? "")

还是不行

【问题讨论】:

  • “但为此我需要链接两个视图”——这不是 SwiftUI 的工作方式。相反,在获取用户名时更新一些视图模型(一个 ObservableObject)。然后,设计要根据此值更新的视图,并带有条件,例如if let userName = vm.userName { ContentView() }
  • 嘿@NewDeve,感谢您的回复。我不太明白你在说什么,我对 SwiftUI 有点陌生
  • @NewDev 我在这里问了另一个问题stackoverflow.com/questions/64859475/…(我添加了更多代码以方便理解)。试着在那里回答,这样我就可以删除这个了。

标签: view swiftui


【解决方案1】:

你的问题太开放了,但我会提供一个答案,希望能帮助你找到正确的方向。

首先,在 SwiftUI 中,将视图的概念(即事物在屏幕上的排列方式)与驱动视图的数据的概念分开。我的意思是,如果你需要一些数据,比如userName,获取它的代码不应该知道或关心哪个视图会使用它。而 Views,不应该关心数据是如何获取的。

其次,在 SwiftUI 中,不应将视图视为具有自己生命周期的“实体”(就像在 UIKit 中一样)。它们只是定义 UI 排列方式的声明性语句。

例如,假设您有这个(假的)class 让用户登录,并且在登录时填充userName 属性。这个类的实例是一个视图模型。

struct User {
   let userName: String
}

class Session: ObservableObject {
   @Published var user: User? = nil

   func signIn(_ completion: (User) -> ()) {
      DispatchQueue.main.asyncAfter(.now() + 0.5) {
         self.user = User(userName: "Mateus") // fake sign-in
         completion(self.user) // not really used in this example
      }
   }
}

@PublishedObservableObject 的组合是 SwiftUI 视图如何知道对该对象的更改作出反应。如果您不知道他们的工作,请阅读更多关于他们的信息。

接下来,设计一个根视图,根据用户是否登录来决定显示什么内部视图:

struct RootView: View {
   @StateObject var session = Session()

   var body: some View {
      VStack() {
         if let user = session.user { 
            ContentView(user: user)  // view is conditionally rendered
         } else {
            Button("sign in") { self.signIn() }
         }
      }
   }

   func signIn() {
      self.session.signIn() {
         print("signed in...!")
      }
   }
}

@StateObject 管理视图的视图模型的生命周期。

正如你在上面看到的,ContentView 只会在session.user 不是nil 时呈现(即当用户登录时),所以视图是由数据的变化驱动的。我不需要提前在任何地方创建ContentView 实例。

那么ContentView就直截了当:

struct ContentView: View {
   var user: User

   var body: some View {
      Text("signed-in username: \(user.userName)")
   }
}

【讨论】:

  • 感谢您再次回复,我刚刚更新了我的问题
  • @MateusNevesdeoliveira,您的更新引入了超出原始范围的更多问题。随时提出新问题。有了这个答案,我只是想给你一个大致的方向
  • 没问题。只是一个简单的问题:在您的代码中,您使用了 ContentView(user: user) 因为您有 "@"StateObject var session = Session() 和 "@"Published var user: User? = 无,对吧?为什么 HomeView(userName: userName) 在我的代码中不起作用,因为在 TransitionView 我有 "@"StateObject var session = SessionStore() 和 "@"Published var userName:Strong = "" ?
  • 我没有完全理解你的代码中发生的事情,所以很难说
猜你喜欢
  • 2021-11-28
  • 2020-12-28
  • 2020-01-10
  • 2020-08-22
  • 1970-01-01
  • 1970-01-01
  • 2020-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多