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
。因此,除此之外,不需要计算属性。