swift 保存到核心数据-循环中的一对多关系

xuo3flqw  于 2023-03-11  发布在  Swift
关注(0)|答案(1)|浏览(131)

我在核心数据中有两个实体。MyMonth和MyPage。每个月都有很多页面,所以它们之间有很多关系。当我保存,更新,删除时,它工作正常。如果我尝试在循环中保存,它只保存一次(或者可能覆盖)。这里的数据模型:
第一节第一节第一节第一节第一次
我从firebase中获取页面,它能完美地获取。获取所有页面后,我运行代码将它们保存到Core Data,如下所示:

func saveBackupPages(firebasePages : [PageModel], savingHandler: @escaping (_ success : Bool) -> Void){
       guard let context = appDelegate?.persistentContainer.viewContext else {
           print("error")
           return
       }
             
       for singlePage in firebasePages {
           let selectedMonth = MyMonth(context: context)
           let selectedPage = MyPage(context: context)

           selectedMonth.name = singlePage.date.getFormattedDate(format: "MMyyyy")
           selectedMonth.userID = FirebaseAuthService.instance.storedUserId
               selectedPage.id = singlePage.id
               selectedPage.body = singlePage.body
               selectedPage.date = singlePage.date
               selectedPage.isFull = singlePage.isFull
               selectedPage.isMarked = singlePage.isMarked
               selectedPage.pic1URL = singlePage.picURL1
               selectedPage.pic2URL = singlePage.picURL2
               selectedPage.pic3URL = singlePage.picURL3
               selectedPage.version = singlePage.version
               selectedMonth.addToPages(selectedPage)
       }
       do {
           try context.save()
           savingHandler(true)
           print("New page created in core data")
       } catch let error {
           print(error)
           savingHandler(false)
       }
   }

当我这样做的时候,它每个月只保存一页。例如,如果我试着保存4页到两个月,每个月2页,它每个月只保存1页。如果我保存20页一个月,它再次只保存一页。所以关系工作,但我认为它覆盖了一个月的页面。
我还从循环中取出了以下代码行:

let selectedMonth = MyMonth(context: context)
let selectedPage = MyPage(context: context)

未修复任何内容。我对核心数据关系非常陌生。我应该如何修复它?
编辑:首先感谢@Joakim Danielson的建议,我做到了:

func saveBackupPages(firebasePases : [PageModel], savingHandler: @escaping (_ success : Bool) -> Void){
        guard let context = appDelegate?.persistentContainer.viewContext else {
            print("error")
            return
        }
        
        let months = [String: MyMonth]()
        
        for singlePage in firebasePases {
            let month = singlePage.date.getFormattedDate(format: "MMyyyy")
            let selectedMonth: MyMonth
            if let existingMonth = months[month] {
                selectedMonth = existingMonth
            } else {
                selectedMonth = MyMonth(context: context)
                selectedMonth.name = month
                selectedMonth.userID = FirebaseAuthService.instance.storedUserId
            }

            let selectedPage = MyPage(context: context)
            selectedPage.id = singlePage.id
            selectedPage.body = singlePage.body
            selectedPage.date = singlePage.date
            selectedPage.isFull = singlePage.isFull
            selectedPage.isMarked = singlePage.isMarked
            selectedPage.pic1URL = singlePage.picURL1
            selectedPage.pic2URL = singlePage.picURL2
            selectedPage.pic3URL = singlePage.picURL3
            selectedPage.version = singlePage.version
            selectedMonth.addToPages(selectedPage)
        }
        
        do {
            try context.save()
            savingHandler(true)
            print("New page created in core data")
        } catch let error {
            print(error)
        }
    }

不幸的是没有工作,或者也许我误解了该怎么做。我使用了4页的同一个月。我只保存了一页。所以我改变了我的函数。现在对于每页和每个月,我的函数首先获取结果,并确定页/月是否存在,然后保存它,如果页不存在于核心数据中。它工作,但效率不高。

alen0pnh

alen0pnh1#

这里的问题是,您要为每个singlePage对象创建一个新的MyMonth示例,并向该月份添加一个MyPage对象。
您需要做的是维护一个本地缓存,以便可以在MyMonth对象存在一个月(“MMyyyy”)后查找和重用它们。
为此,我们创建了一个本地字典来保存MyMonth对象。

var months = [String: MyMonth]()

然后,在for循环的顶部,我们提取当前月份,并将其用作检查是否有MyMonth对象或是否需要创建一个新对象的键

for singlePage in firebasePages {
    let month = singlePage.date.getFormattedDate(format: "MMyyyy")
    let selectedMonth: MyMonth
    if let existingMonth = months[month] {
        selectedMonth = existingMonth
    } else {
        selectedMonth = MyMonth(context: context)
        selectedMonth.name = month
        selectedMonth.userID = FirebaseAuthService.instance.storedUserId
    }
   // rest of the code in the loop is the same
}

您可以通过在函数中创建新对象来稍微清理代码

func make(month: String) -> MyMonth {
    let newMonth = MyMonth(context: context)
    newMonth.name = month
    newMonth.userID = FirebaseAuthService.instance.storedUserId
    return newMonth
}

则循环中的上述代码可以用更短的方式编写

for singlePage in firebasePages {
    let month = singlePage.date.getFormattedDate(format: "MMyyyy")
    let selectedMonth = months[month, default: make(month: month)]
   // rest of the code in the loop is the same
}

相关问题