确保核心数据@FetchRequest 变量动态运行需要哪些代码更改(附加代码)?

Posted

技术标签:

【中文标题】确保核心数据@FetchRequest 变量动态运行需要哪些代码更改(附加代码)?【英文标题】:What code changes (code attached) required to ensure core data @FetchRequest variable behaves dynamically? 【发布时间】:2019-10-28 11:59:15 【问题描述】:

应该如何修改我的代码以确保在添加新项目时核心数据层发生异常时,SwiftUI 不会继续显示新项目?

背景:当我运行以下代码时,在添加执行“context.save()”的新项目时出现异常,但是,虽然新项目请求确实失败了(没有保存到核心数据),但 UI 确实显示一个新项目。就好像@FetchRequest 行中的“列表”变量没有动态运行。

问题 - 如何修复代码以使应用程序正常运行?

代码:

import SwiftUI

struct ContentView: View 
    @Environment(\.managedObjectContext) var context
    @FetchRequest(fetchRequest: List.allListFetchRequest()) var lists: FetchedResults<List>

    private func addListItem() 
        let newList = List(context: context)
        newList.id = 1
        newList.title = "Testing 123"
        do 
            try context.save()
         catch let e as NSError 
            print("Could not save new List. \(e.debugDescription)")
            return
        

    

    var body: some View 
        NavigationView 
            VStack 
                ForEach(lists)  list in
                    Text("List = \(list.title)")
                
            
            .navigationBarTitle( Text("My Todo Lists") )
            .navigationBarItems(
                trailing: Button(action: self.addListItem() ) 
                    Image(systemName: "plus.square")
                
            )
        
    

示例输出:

Could not save new List. Error Domain=NSCocoaErrorDomain Code=133021 "(null)" UserInfo=NSExceptionOmitCallstacks=true, conflictList=(
    "NSConstraintConflict (0x600001fcccc0) for constraint (\n    id\n): database: (null), conflictedObjects: (\n    \"0x600000a7e360 <x-coredata:///List/t2F01130C-0D2A-4E88-A77D-A7BA0E921C213>\",\n    \"0xfb1bb528bb57810c <x-coredata://41B391F1-A95C-4971-9584-A2D3DFFF5380/List/p3>\"\n)"
)

【问题讨论】:

是的,模拟失败场景 如果一个新项目不能/没有被添加,那么我不希望 UI 向用户表明它已经添加了 您可以尝试在catch 块中手动fetch 吗? 【参考方案1】:

Jim Dovey 用这个建议给了我前进的方向:

private func addListItem()   
    context.performBlock  context in  
        let newList = List(context: context)  
        newList.id = 1  
        newList.title = "Testing 123"  
        do   
            try context.save()  
          
        catch   
            print("Failed to save new item. Error = \(error)")  
            context.delete(newList)  
            // don't need to save here, because we're in `performBlock` and have reverted the only unsaved change.  
          
      
 

【讨论】:

以上是关于确保核心数据@FetchRequest 变量动态运行需要哪些代码更改(附加代码)?的主要内容,如果未能解决你的问题,请参考以下文章

NSArray 作为核心数据 fetchRequest 中的参数

Swift 核心数据 FetchRequest NSData 到 UIIMage

可可 iphone 核心数据谓词一对多 fetchrequest

iOS:在 fetchrequest 中仅获取核心数据中的简单信息

核心数据:如何显示 fetchrequest 的结果以计算表格视图单元格中的值

预览因核心数据查找而失败,但在 Swift 5 / Core Data / FetchRequest 中使用随机值