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

问题描述 投票:0回答:1

我在核心数据中有两个实体。我的月份和我的页面。 每个月都有很多页,所以它们之间是一对多的关系。当我保存、更新、删除时,它工作正常。如果我尝试在循环中保存,它只会保存一次(或者可能会覆盖)。 这里的数据模型:

我从 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 页。我只保存了一页。所以我改变了我的功能。现在对于每个页面和月份,我的函数首先获取结果并确定页面/月份是否存在,如果页面不存在于核心数据中则保存它。它有效,但效率不高。

swift loops core-data save relationship
1个回答
1
投票

这里的问题是您正在为每个

MyMonth
对象创建一个新的
singlePage
实例,并向该月添加一个
MyPage
对象。

你需要做的是维护一个本地缓存,这样当它们存在一个月(“MMyyyy”)时,你可以查找和重用现有的

MyMonth
对象。

我们通过创建一个本地字典来保存

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
} 
© www.soinside.com 2019 - 2024. All rights reserved.