SwiftUI中如何将FetchedResults数据转换为对象数组
解决方案:将CoreData实体转换为内存对象管理复选框状态
1. 创建内存用的数据模型结构体
先定义一个结构体,专门存储CoreData实体的必要数据,以及仅在内存中管理的复选框选中状态:
struct ParticipantModel: Identifiable { // 用CoreData实体的objectID作为唯一标识(保证唯一性) let id: NSManagedObjectID let firstName: String let lastName: String let groupName: String let profilePicture: String? // 仅在内存中维护的选中状态 var isChecked: Bool }
2. 转换CoreData数据为内存对象数组
在View中,通过@FetchRequest获取CoreData数据后,将其转换为上述结构体的数组,用@State管理这个内存数组,并监听CoreData数据变化以同步更新:
struct YourView: View { @FetchRequest( entity: ParticipantEntity.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \ParticipantEntity.first_name, ascending: true)] ) private var participantItems: FetchedResults<ParticipantEntity> // 内存中的对象数组,专门管理选中状态 @State private var participantModels: [ParticipantModel] = [] var body: some View { List { // 通过绑定直接修改内存中的选中状态 ForEach($participantModels) { $model in HStack { AsyncImage( url: URL(string: url + (model.profilePicture ?? "")), content: { image in image.resizable() .aspectRatio(contentMode: .fit) .frame(maxWidth: 45, maxHeight: 45) .cornerRadius(5) }, placeholder: { Image("no_profile_pic") .resizable() .frame(maxWidth: 45, maxHeight: 45) } ) VStack(alignment: .leading) { let name = "\(model.firstName) \(model.lastName)" Text(name) Text(model.groupName) } .padding(.leading, 5) Spacer() Image(systemName: model.isChecked ? "checkmark.square" : "square") .onTapGesture { // 仅修改内存中的状态,不会改动CoreData数据库 model.isChecked.toggle() } } } } .listStyle(PlainListStyle()) // 页面加载时初始化内存数组 .onAppear { updateParticipantModels() } // 监听CoreData数据变化,自动同步内存数组 .onChange(of: participantItems) { _ in updateParticipantModels() } } // CoreData实体转内存模型的方法 private func updateParticipantModels() { participantModels = participantItems.map { entity in ParticipantModel( id: entity.objectID, firstName: entity.first_name ?? "", lastName: entity.last_name ?? "", groupName: entity.group_name ?? "No Group Name", profilePicture: entity.profile_picture, isChecked: false // 初始选中状态可按需调整 ) } } }
进阶:保留CoreData数据更新时的选中状态
如果需要在CoreData数据变化时,不丢失已有的选中状态,可以修改updateParticipantModels方法,匹配id保留状态:
private func updateParticipantModels() { let newModels = participantItems.map { entity -> ParticipantModel in // 查找原有数组中相同id的模型,继承选中状态 if let existingModel = participantModels.first(where: { $0.id == entity.objectID }) { return ParticipantModel( id: entity.objectID, firstName: entity.first_name ?? "", lastName: entity.last_name ?? "", groupName: entity.group_name ?? "No Group Name", profilePicture: entity.profile_picture, isChecked: existingModel.isChecked ) } else { return ParticipantModel( id: entity.objectID, firstName: entity.first_name ?? "", lastName: entity.last_name ?? "", groupName: entity.group_name ?? "No Group Name", profilePicture: entity.profile_picture, isChecked: false ) } } participantModels = newModels }
内容的提问来源于stack exchange,提问作者Carole Malonda
相关产品推荐
相关产品推荐

