SwiftUI+CoreData重排列表报错:'order'为只读属性
问题解决:CoreData列表重排时的只读属性错误
你遇到的Cannot assign to property: 'order' is a get-only property错误,根源在于MyBookmarkViewModel里的order属性只有只读的getter,且内部持有的CoreData实体对象是不可变的let常量,无法直接修改实体的order值。以下是具体修复步骤:
1. 修改MyBookmarkViewModel,让order属性可写
把内部的myBM从let改为var,并给order添加setter方法,直接映射到CoreData实体的order属性:
struct MyBookmarkViewModel: Identifiable, Hashable { init(myBM: MyBookmark) { self.myBM = myBM } // 将let改为var,允许修改内部CoreData实体 private var myBM: MyBookmark var id: NSManagedObjectID { myBM.objectID } var name: String { myBM.name ?? "" } // 添加getter和setter,直接操作CoreData实体的order属性 var order: Int64 { get { myBM.order } set { myBM.order = newValue } } }
2. 完善reorderItems方法,持久化排序修改
修改完order值后,必须保存CoreData上下文才能让排序变化永久生效,否则重启App后排序会还原:
func reorderItems(from source: IndexSet, to destination: Int) { // 先更新ViewModel数组的内存顺序 myBookmarks.move(fromOffsets: source, toOffset: destination ) // 反向遍历更新每个item的order值,避免索引混乱 for reserveIndex in stride(from: myBookmarks.count - 1, through: 0, by: -1 ) { myBookmarks[reserveIndex].order = Int64(reserveIndex) } // 保存CoreData上下文,持久化排序修改 do { try context.save() } catch { let nsError = error as NSError fatalError("排序保存失败: \(nsError), \(nsError.userInfo)") } }
3. 实现FetchedResultsController代理,同步数据变化
确保ViewModel能监听CoreData的变化,自动更新myBookmarks数组:
extension MyBookmarksViewModel: NSFetchedResultsControllerDelegate { func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { guard let fetchedItems = controller.fetchedObjects as? [MyBookmark] else { return } myBookmarks = fetchedItems.map(MyBookmarkViewModel.init) } }
同时在ViewModel初始化时执行一次数据拉取,加载初始列表:
init(context: NSManagedObjectContext){ self.context = context self.fetchedResultsController = NSFetchedResultsController(fetchRequest: MyBookmark.all, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil) super.init() fetchedResultsController.delegate = self // 初始加载数据 do { try fetchedResultsController.performFetch() if let items = fetchedResultsController.fetchedObjects { myBookmarks = items.map(MyBookmarkViewModel.init) } } catch { print("初始数据加载失败: \(error)") } }
内容的提问来源于stack exchange,提问作者swiftnoob
相关产品推荐
相关产品推荐

