SwiftUI - 如何切换核心数据中的所有布尔值
Posted
技术标签:
【中文标题】SwiftUI - 如何切换核心数据中的所有布尔值【英文标题】:SwiftUI - How to toogle all the booleans in a CoreData 【发布时间】:2020-04-23 21:19:02 【问题描述】:我有一个数据库,其中包含多个以布尔值作为属性的对象。我正在寻找一个函数来在我按下按钮时反转所有布尔对象。我尝试了这个功能,但显示了几个错误,例如('Bool' 类型的值没有成员'indices'):
struct ViewList: View
@Environment(\.managedObjectContext) var context
@State var newName: String = ""
@FetchRequest(
entity: Product.entity(),
sortDescriptors: [NSSortDescriptor(keyPath: \Product.name, ascending: true)]
) var list: FetchedResults<Product>
var body: some View
VStack
HStack
TextField("I insert the name of the product", text: $newName)
Button(action: self.add()
self.newName = ""
)
Image(systemName: "plus")
List
ForEach(list, id: \.self)
product in ViewItem(product: product)
public func add()
let newProduct = Product(context: context)
newProduct.name = newName
do
try context.save()
catch
print(error)
struct ViewItem: View
@State var product: Product
@State var refresh: Bool = false
var body: some View
NavigationLink(destination: ViewDetail(product: product, refresh: $refresh))
HStack(alignment: .top)
Button( action:
self.clean()
self.product.isSelected.toggle()
)
if self.product.isSelected == true
Image(systemName: "checkmark")
else
Image(systemName: "checkmark").colorInvert()
VStack()
Text(product.name)
if product.password != ""
Text("Password : " + product.password)
Text(String(refresh)).hidden()
.onAppear
self.refresh = false
我一直在想,但我不知道该怎么做……
func clean()
for( index ) in self.product.isSelected.indices
self.product[index]isSelected = false
【问题讨论】:
您的 var 产品是 Product 的单个实例。看起来作为 FetchRequest 输出的 var 列表是您应该迭代的东西。 @WarrenBurton : 我想把函数放在结构 ViewItem 中,当我在结构 VeiwItem 中时如何检索数据库“列表”? 您想翻转列表中所有产品的选中状态?还是只是 ViewItem 中的一种产品? 我明白了,你有一个表格视图,当你选择一个项目时,你想取消选择之前的选择。在数据(模型)中存储选择(视图)状态并不是一个很好的设计选择。一种可能的模式是创建一个选择处理程序类来记住选择状态,将该对象传递给 ViewItem 并使用它来更改选择。看看raywenderlich.com/7705231-creating-a-mind-map-ui-in-swiftui中的选择机制,我明天会尝试回答问题 @WarrenBurton:谢谢你的链接,我会研究这个。我已将布尔值 isSelected 放入实体产品中,因为我想将其存储在 Coredata 中,并在下次启动应用程序时重新查找所选产品。因此,当显示产品的 ViewDetail 时,必须在数据库中取消选择之前选择的产品。 【参考方案1】:您需要创建一个查询来翻转isSelected
标志的状态。最好不要将此逻辑置于视图系统之外,以便您可以在任何地方使用它。
你创建一个SelectionHandler
import CoreData
class SelectionHandler
func clearSelection(in context: NSManagedObjectContext)
for item in currentSelected(in: context)
item.isSelected = false
func selectProduct(_ product: Product)
guard let context = product.managedObjectContext else
assertionFailure("broken !")
return
clearSelection(in: context)
product.isSelected = true
func currentSelected(in context: NSManagedObjectContext) -> [Product]
let request = NSFetchRequest<Product>(entityName: Product.entity().name!)
let predicate = NSPredicate(format: "isSelected == YES")
request.predicate = predicate
do
let result = try context.fetch(request)
return result
catch
print("fetch error =",error)
return []
然后您可以使用它来选择您想要的产品。
SelectionHandler().selectProduct(product)
就目前而言,您的 NavigationLink
不会执行任何操作,因为父列表未保存在 NavigationView
中,因此您需要将 ViewList
的正文更改为如下所示。
var body: some View
NavigationView
VStack
HStack
TextField("Create product with name", text: $newName)
Button(action:
self.add()
self.newName = ""
)
Image(systemName: "plus")
.padding()
List
ForEach(list, id: \.self) product in
ViewItem(product: product)
在 ViewItem
中,Product
应该是 ObservedObject
,以便在 managedObject 中检测到更改。
struct ViewItem: View
@ObservedObject var product: Product
@State var refresh: Bool = false
var checkmarkImage: some View
return Group
if self.product.isSelected
Image(systemName: "checkmark")
else
Image(systemName: "checkmark").colorInvert()
var body: some View
NavigationLink(destination: ViewDetail(product: product, refresh: $refresh))
HStack
checkmarkImage
Text(product.name ?? "wat")
原来的Button
不会与NavigationLink
一起使用,但您可以简单地将选择应用于ViewDetail
中的onAppear
struct ViewDetail: View
@ObservedObject var product: Product
@Binding var refresh: Bool
var body: some View
VStack
Text("Hello, World!")
Text("Product is \(product.name ?? "wat")")
.onAppear
SelectionHandler().selectProduct(self.product)
【讨论】:
非常感谢!正是我需要的。再次感谢。以上是关于SwiftUI - 如何切换核心数据中的所有布尔值的主要内容,如果未能解决你的问题,请参考以下文章
如何选择一个 TableViewCell 并将所有其他单元格设置为 CoreData 中的布尔值 NO?