Binding 如何在SwiftUI中绑定计算属性
我有一个简单的模型声明:Binding 如何在SwiftUI中绑定计算属性,binding,swiftui,Binding,Swiftui,我有一个简单的模型声明: struct Claim: Codable, Identifiable { let id: String var name: String var isSelected: Bool? = nil // used for selecting claims in a list } AddClaimView用于筛选出已存储在角色中的声明。声明,并将其显示在列表中,供用户选择以添加到角色 struct AddClaimView: View {
struct Claim: Codable, Identifiable {
let id: String
var name: String
var isSelected: Bool? = nil // used for selecting claims in a list
}
AddClaimView用于筛选出已存储在角色中的声明。声明
,并将其显示在列表中,供用户选择以添加到角色
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())
}
}
}
过滤是由computed属性claimsforading
完成的,问题来了。
如何将计算属性claimsforading
绑定到claimsslistrow
视图中的@Binding var claims
,然后将它们添加到角色。claims
@State var claimsforading….
显然不适用于计算属性
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
}
))
}
}
}
struct AddClaimView:View{
风险值索赔:[索赔]
@绑定变量角色:角色
var索赔:[索赔]{
得到{
self.claims.filter{claim in
!self.role.claims.contains(索赔)
}
}
设置{
var索赔=自我索赔
removeAll(其中:{claim in
newValue.contains(索赔)
})
}
}
var body:一些观点{
VStack{
文本(“添加索赔”)
.font(.largeTitle)
权利要求书(权利要求:有约束力)(
获取:{
self.claims.filter{
在!self.role.claims.contains中声明(声明)
}
.排序(按:{$0.name<$1.name})
},
集合:{newValue in
var索赔=自我索赔
removeAll(其中:{claim in
newValue.contains(索赔)
})
self.role.claims=索赔
}
))
}
}
}
您需要创建一个自定义的绑定来更新角色:
ClaimsListRows(声明:绑定)(
获取:{
self.claims.filter{
在!self.role.claims.contains中声明(声明)
}
.排序(按:{$0.name<$1.name})
},
集合:{newValue in
var索赔=自我索赔
removeAll(其中:{claim in
newValue.contains(索赔)
})
self.role.claims=索赔
}
))
为什么要使用@Binding
而不是将列表作为常量传递?ClaimsListRows
是否需要更改列表?需要使用role.claims
列表中添加的声明更新role
属性。如果我将该列表作为常量传递,则无法更新角色
。啊,因此您需要手动定义一个绑定
,以便设置
更新角色
。是的,我在ClaimsListRows
:@Binding var claims:[声明]
。您不需要更改claimstrows
,只需将自定义绑定
传递给它的构造函数。这看起来很有希望,我会尝试一下,并尝试了解它的功能。它定义了双向绑定
。您在claimsforading
中编写了get
部分,但您遗漏了set
部分,该部分用于确定值中的更改如何更新原始变量。根据您的评论,我已使用set
部分更新了claimsforading
计算属性,如您在回答中所示。但我不知道你的回答中的声明是什么。这是否显示结构声明?有参数吗?它应该是ClaimsListRows
的init
方法吗?很抱歉,我不太明白。ClaimsListRows
构造函数接受一个Binding
参数。在我的回答中,我向它传递了一个自定义绑定,该绑定获取过滤后的声明并设置角色.claims
。因此,除此之外,不需要计算属性。