有没有办法使用 SwiftUI 和 Firebase 动态地在属性初始化程序中的实例中赋予初始值?
Posted
技术标签:
【中文标题】有没有办法使用 SwiftUI 和 Firebase 动态地在属性初始化程序中的实例中赋予初始值?【英文标题】:Is there a way to give initial value in an instance in property initializer dynamically using SwiftUI and Firebase? 【发布时间】:2020-04-29 04:07:22 【问题描述】:您好,我目前正在制作一个约会应用的聊天页面,您可以使用 SwiftUI 和 Cloud Firestore 为每场比赛设置不同的房间。
我想根据 matchId 每次点击首页上的不同用户时显示不同的聊天室。
现在,我需要在视图文件中键入正确的,以使其正常工作,但是,我想动态分配它。
如何将正确的 matchId 添加到视图文件中的实例?或者,我应该尝试不同的方式吗?
首先,这是首页。
VStack
Text("Match Users")
List(self.shareData.matchUserArray) user in
NavigationLink(destination: MessageView(matchUserInfo: user))
HStack
Text(user.name)
Text(user.age)
这是视图文件。无需在 MessageViewModel 实例中键入“Ll73RINefGxEcYQJoWSE”而是给它“”,我可以在调试区域中看到消息,但在列表中看不到任何消息。
struct MessageView: View
var matchUserInfo: User
@ObservedObject var msgVM = MessageViewModel(matchId: "Ll73RINefGxEcYQJoWSE")
@EnvironmentObject var shareData : ShareData
@State var text = ""
@State var matchId = ""
var body: some View
VStack
List(self.msgVM.messages, id: \.id) i in
if i.fromUser == self.shareData.currentUserData["id"] as? String ?? ""
MessageRow(message: i.msg, isMyMessage: true)
else if i.toUser == self.shareData.currentUserData["id"] as? String ?? ""
MessageRow(message: i.msg, isMyMessage: false)
.onAppear UITableView.appearance().separatorStyle = .none
.onDisappear UITableView.appearance().separatorStyle = .singleLine
HStack
TextField("message here", text: $text).textFieldStyle(RoundedBorderTextFieldStyle()).padding()
Button(action:
if self.text.count > 0
self.msgVM.sendMsg(msg: self.text, toUser: self.matchUserInfo.id, fromUser: self.shareData.currentUserData["id"] as! String, matchId: self.msgVM.matchId)
self.text = ""
)
Image(systemName: "paperplane")
.padding(.trailing)
.navigationBarTitle("\(self.matchUserInfo.name)", displayMode: .inline)
.onAppear
DispatchQueue.global().async
self.getMatchId(partner: self.matchUserInfo)
_ = MessageViewModel(matchId: self.matchId)
.onDisappear
print(self.msgVM.messages)
func getMatchId(partner: User)
Firestore.firestore().collection("MatchTable").document(self.shareData.currentUserData["id"] as? String ?? "").collection("MatchUser").whereField("MatchUserId", isEqualTo: partner.id).getDocuments (snap, err) in
if let snap = snap
for id in snap.documents
self.msgVM.matchId = id.data()["MatchRoomId"] as? String ?? ""
_ = MessageViewModel(matchId: self.msgVM.matchId)
self.matchId = self.msgVM.matchId
这也是 firebase 部分。
import Foundation
import FirebaseFirestore
struct Message: Identifiable
var id: String
var msg: String
var fromUser: String
var toUser: String
var date: Timestamp
var matchId : String
class MessageViewModel: ObservableObject
var datas = FirebaseData()
let db = Firestore.firestore()
@Published var matchId:String
@Published var messages = [Message]()
init(matchId: String)
self.matchId = matchId
self.db.collection("Messages").whereField("matchId", isEqualTo: self.matchId).order(by: "date").addSnapshotListener (snap, error) in
if let error = error
print(error.localizedDescription)
return
if let snap = snap
for i in snap.documentChanges
if i.type == .added
let toUser = i.document.get("toUser") as! String
let fromUser = i.document.get("fromUser") as! String
let message = i.document.get("message") as! String
let id = i.document.documentID
let date = i.document.get("date") as! Timestamp
let matchId = i.document.get("matchId") as! String
self.messages.append(Message(id: id, msg: message, fromUser: fromUser, toUser: toUser, date: date, matchId: matchId))
func sendMsg(msg: String, toUser: String, fromUser: String, matchId: String)
let data = [
"message": msg,
"toUser": toUser,
"fromUser": fromUser,
"date": Timestamp(),
"matchId": matchId
] as [String : Any]
Firestore.firestore().collection("Messages").addDocument(data: data) error in
if let err = error
print(err.localizedDescription)
return
print("Sent message")
谢谢
【问题讨论】:
【参考方案1】:您真正需要的是在init
函数中构造您的ObservedObject
:
let matchUserInfo: User
@ObservedObject private var msgVM: MessageViewModel
init(_ user: User)
self.matchUserInfo = user
self._msgVM = ObservedObject(initialValue: MessageViewModel(matchId: user.matchId))
当然,假设您关心的 matchId
是通过您的 User
类型传入的。你比我更了解你的数据结构,这里的关键是根据你传入的 User
简单地创建你观察到的对象。
【讨论】:
我对 matchUserArray 的元素进行了一些更改,以便每个传入的用户都有 matchId,并且一切都开始运行良好。非常感谢,它很有帮助! @Procrastin8以上是关于有没有办法使用 SwiftUI 和 Firebase 动态地在属性初始化程序中的实例中赋予初始值?的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法使用几何阅读器将我的 SwiftUI 图像的宽度定义为相对于屏幕尺寸?
有没有办法为 SwiftUI 菜单使用 .displayInline 选项?
有没有办法在 macOS SwiftUI 开发中使用 SF Symbols?
SwiftUi 有没有办法在 TextField 中获取文本