swift - SwiftUI - 为 UI 切换动态添加 @State
问题描述
我目前正在从 Firebase Firestore 获取网站列表,然后将它们返回到 SwiftUI 中的列表。每个列表项都有一个标签和切换。站点列表是动态的,因此可以是 1-30 多个。如何创建 @State 或类似的可绑定对象来观察每个切换的状态。
我目前正在使用以下内容渲染到 UI
@State private var SiteA = false
Form {
Section (header: Text("Select Sites")) {
ForEach(siteData.sites) { site in
HStack {
Toggle(isOn: self.$SiteA) {
Text(site.name)
Spacer()
}
}
}
}
}
使用 Bindable 对象检索站点
import SwiftUI
import Combine
import Firebase
import FirebaseFirestore
struct Message: Identifiable {
var title: String
var messageBody: String
var sentBy: String
var targetSite: String
var expired: Bool
var timeStamp: Timestamp
var emergency: Bool
var id: String
}
struct Site: Identifiable {
var id: String
var name: String
}
class FirestoreMessages : ObservableObject {
var db = Firestore.firestore()
var didChange = PassthroughSubject<FirestoreMessages, Never>()
@Published var messages: [Message] = [] {
didSet{ didChange.send(self) }
}
@Published var sites: [Site] = [] {
didSet { didChange.send(self) }
}
func listen() {
db.collection("messages")
.whereField("expired", isEqualTo: false)
.addSnapshotListener { (snap, error) in
if error != nil {
print("Firebase Snapshot Error: \(error?.localizedDescription ?? "")")
} else {
self.messages.removeAll()
for doc in snap!.documents {
let title = doc["title"] as! String
let messageBody = doc["body"] as! String
let sentBy = doc["sentBy"] as! String
let targetSite = doc["targetSite"] as! String
let expired = doc["expired"] as! Bool
let timeStamp = doc["timeStamp"] as! Timestamp
let emergency = doc["emergency"] as! Bool
let id = doc.documentID
let message = Message(
title: title,
messageBody: messageBody,
sentBy: sentBy,
targetSite: targetSite,
expired: expired,
timeStamp: timeStamp,
emergency: emergency,
id: id)
self.messages.append(message)
}
}
}
}
func getSites() {
db.collection("sites")
.order(by: "name", descending: false)
.getDocuments() { (querySnapshot, err) in
if let err = err {
print("Error getting docs: \(err)")
} else {
self.sites.removeAll()
for document in querySnapshot!.documents {
let doc = document.data()
let id = document.documentID
let name = doc["name"] as! String
let site = Site(id: id, name: name)
self.sites.append(site)
}
}
}
}
}
如何@State
为每个列表项创建一个唯一项以单独监视它们的状态?
解决方案
你的问题的答案是作文。将 HStack 和封闭的 Toggle 移动到 SiteRow 视图,其中每一行都有自己的状态。
struct SiteRow: View {
@State private var state: Bool = false
private let site: Site
init(_ site: Site) {
self.site = site
self.state = site.isOn
}
var body: some View {
HStack {
Toggle(isOn: self.$state) {
Text(site.name)
Spacer()
}
}
}
}
然后...
ForEach(siteData.sites) { site in SiteRow(site) }
推荐阅读
- xml - XQuery - 仅获取查询值
- node.js - Ngrok(应用程序)子域
- typo3 - 如何在typo3 tx_news 中链接标签?
- arrays - 如何检查对象数组是否有值或未定义-Reactjs,数组
- r - 如何将特定长度和数量的随机连续间隙插入向量中?
- typescript - Visual Studio Code 无法扫描类型定义
- javascript - 将值传递给回调函数
- c - DatagridView 特定列搜索值并选择没有文本框的单元格
- .net - Windows 10 中的 .NET 3.5 + TLS 1.1/1.2 支持
- javascript - 在 JavaScript 中单击后更改类名称