binding - 如何在 SwiftUI 中绑定计算属性
问题描述
我有一个简单的模型声明:
struct Claim: Codable, Identifiable {
let id: String
var name: String
var isSelected: Bool? = nil // used for selecting claims in a list
}
AddClaimView 用于过滤掉已经存储role.claims
在role
.
struct AddClaimView: View {
var claims: [Claim] // all possible claims
@Binding var role: Role
var claimsForAdding: [Claim] {
self.claims.filter { claim in
!self.role.claims.contains(claim)
}
}
var body: some View {
VStack {
Text("Add claim")
.font(.largeTitle)
ClaimsListRows(claims: self.claimsForAdding.sorted())
}
}
}
过滤是由计算属性完成的claimsForAdding
,问题就来了。如何将计算属性绑定claimsForAdding
到视图@Binding var claims
中ClaimsListRow
,然后将它们添加到role.claims
?
@State var claimsForAdding....
显然不适用于计算属性。
struct ClaimsListRows: View {
@Binding var claims: [Claim]
var body: some View {
List(claims) { claim in
// set property isSelected = true when tapping a row
.....
在工作表中呈现的视图AddClaimView
:
struct RoleDetailed: View {
@Binding var role: Role
@State var showAddClaim = false
@Binding var claims: [Claim]
var body: some View {
VStack(alignment: .leading) {
HStack {
Text(role.name)
.font(.largeTitle)
Spacer()
}
Text("id: " + role.id)
.font(.footnote)
.foregroundColor(Color.gray)
List {
ForEach(role.claims) { claim in
ClaimRow(claim: claim)
}
}
}.font(.headline).padding(10)
.navigationBarItems(trailing:
Button(action: {
self.showAddClaim.toggle()
}) {
Text("Add claim")
}.sheet(isPresented: self.$showAddClaim, onDismiss: {
print("dismissed")
}, content: {
AddClaimView(claims: self.claims, role: self.$role)
})
)
}
}
根据我收到的评论,这是新的AddClaimView
:
struct AddClaimView: View {
var claims: [Claim]
@Binding var role: Role
var claimsForAdding: [Claim] {
get {
self.claims.filter { claim in
!self.role.claims.contains(claim)
}
}
set {
var claims = self.claims
claims.removeAll(where: { claim in
newValue.contains(claim)
})
}
}
var body: some View {
VStack {
Text("Add claim")
.font(.largeTitle)
ClaimsListRows(claims: Binding<[Claim]>(
get: {
self.claims.filter {
claim in !self.role.claims.contains(claim)
}
.sorted(by: { $0.name < $1.name })
},
set: { newValue in
var claims = self.claims
claims.removeAll(where: { claim in
newValue.contains(claim)
})
self.role.claims = claims
}
))
}
}
}
解决方案
您需要创建一个Binding
更新角色的自定义:
ClaimsListRows(claims: Binding<[Claim]>(
get: {
self.claims.filter {
claim in !self.role.claims.contains(claim)
}
.sorted(by: { $0.name < $1.name })
},
set: { newValue in
var claims = self.claims
claims.removeAll(where: { claim in
newValue.contains(claim)
})
self.role.claims = claims
}
))
推荐阅读
- java - 尝试获取 pivotCacheDefinition 时无法解析类 org.apache.poi.ooxml.POIXMLDocumentPart
- python - Defaultdict 自动为每个键创建一个子字典?
- html - 使用 BeautifulSoup 从 URL 抓取数据并将其保存到 csv
- recaptcha-v3 - 带附件的文件不发送
- discord.py - 如何让嵌入与 discord.py 一起使用?
- java - 有人可以帮我处理这段代码吗,它没有返回我想要的结果
- r - 将箱线图与 Wilcoxon 检验进行比较
- javascript - 在不使用 gmail smtp 的情况下发送电子邮件 nodemailer
- assembly - 链接汇编程序生成的 obj 文件
- c - memset上的程序崩溃?