iOS - 数据保存一次到核心数据中

Posted

技术标签:

【中文标题】iOS - 数据保存一次到核心数据中【英文标题】:iOS - Data persist once into Core Data 【发布时间】:2016-02-19 01:06:01 【问题描述】:

我正在尝试将一堆数据保存到核心数据中。我可以设法将所有数据保存到核心数据中,但是在核心数据中包含重复数据是没有意义的,因为该函数将在项目的每个构建中执行一次。我现在考虑的方法是在向实体添加新记录之前清空实体记录。只是想知道是否有另一种方法来确保数据只保留一次?

func persistCurrencyData() 
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

    let managedContext = appDelegate.managedObjectContext

    let currencyEntity = NSEntityDescription.entityForName("Currency", inManagedObjectContext: managedContext)


    let countryEntity = NSEntityDescription.entityForName("Country", inManagedObjectContext: managedContext)

    for currency in currencies 
      let currencyObject = CurrencyCore(entity: currencyEntity!, insertIntoManagedObjectContext: managedContext)

      currencyObject.setValue(currency.code, forKeyPath: "code")
      currencyObject.setValue(currency.name, forKeyPath: "name")

      for country in currency.country! 
        let countryObject = CountryCore(entity: countryEntity!, insertIntoManagedObjectContext: managedContext)

        countryObject.setValue(country.name, forKeyPath: "name")
        countryObject.setValue(country.code, forKeyPath: "code")
        countryObject.setValue(country.continent, forKeyPath: "continent")
        countryObject.setValue(country.continentCode, forKeyPath: "continentCode")

        countryObject.currency = currencyObject
      
    

    do 
      try managedContext.save()
     catch let error as NSError  
      print("Could not save \(error), \(error.userInfo)")
    

更新:

感谢@Wain 给了我这个想法。基本上,我为解决在核心数据中保存重复数据所做的工作是在我的 JSON 文件中包含了一个 GUID。代码每次读取 JSON 文件时,都会将 GUID 保存到NSUserDefault,并将数据保存到核心数据中。当它想在下一次构建中再次读取 JSON 文件时,它会检查 GUID 是否与之前保存的 GUID 相同。如果不同,代码将读取 JSON 文件并重复上述过程。如果不是,它将继续并忽略它。

func requestCurrenciesData() 
    getCurrenciesDataFromFileWithSuccess  (data) -> Void in
      var json: [String: AnyObject]

      do 
        json = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions()) as! [String: AnyObject]

        guard let currencyData = CurrencyData(json: json) else 
          print("Error initializing object")
          return
        

        self.currencies = currencyData.currency!

        // Checking the JSON's id is same as previous read
        let defaults = NSUserDefaults.standardUserDefaults()
        if let id = defaults.stringForKey("id")
        
          if id == currencyData.id 
            let notification = NSNotification(name: "CurrenciesDataUpdate", object: nil)
            NSNotificationCenter.defaultCenter().postNotification(notification)

            return
          
        

        self.persistCurrencyDataForId(currencyData.id)

        let notification = NSNotification(name: "CurrenciesDataUpdate", object: nil)
        NSNotificationCenter.defaultCenter().postNotification(notification)
       catch 
        print(error)
        return
      
   


func persistCurrencyDataForId(id: String) 
    // Save the new JSON's id into NSUserDefaults
    let defaults = NSUserDefaults.standardUserDefaults()
    defaults.setObject(id, forKey: "id")

    // Delete all the records in existing table
    deleteRecordsFromEntity("Country")
    deleteRecordsFromEntity("Currency")

    // Insert the new records
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let managedContext = appDelegate.managedObjectContext

    let currencyEntity = NSEntityDescription.entityForName("Currency", inManagedObjectContext: managedContext)
    let countryEntity = NSEntityDescription.entityForName("Country", inManagedObjectContext: managedContext)

    for currency in currencies 
      let currencyObject = CurrencyCore(entity: currencyEntity!, insertIntoManagedObjectContext: managedContext)

      currencyObject.setValue(currency.code, forKeyPath: "code")
      currencyObject.setValue(currency.name, forKeyPath: "name")

      for country in currency.country! 
        let countryObject = CountryCore(entity: countryEntity!, insertIntoManagedObjectContext: managedContext)

        countryObject.setValue(country.name, forKeyPath: "name")
        countryObject.setValue(country.code, forKeyPath: "code")
        countryObject.setValue(country.continent, forKeyPath: "continent")
        countryObject.setValue(country.continentCode, forKeyPath: "continentCode")

        countryObject.currency = currencyObject
      
    

    do 
      try managedContext.save()
     catch let error as NSError  
      print("Could not save \(error), \(error.userInfo)")
    
  

func deleteRecordsFromEntity(entityName: String) 
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let managedContext = appDelegate.managedObjectContext
    let coordinator = appDelegate.persistentStoreCoordinator

    let fetchRequest = NSFetchRequest(entityName: entityName)
    let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)

    do 
      try coordinator.executeRequest(deleteRequest, withContext: managedContext)
     catch let error as NSError 
      print(error)
    
 

【问题讨论】:

您导入的数据来自哪里?每次运行此代码时它是否会发生变化?每个对象都有唯一的标识符吗? @Wain 从json 文件中提取数据,每次代码运行时数据都相同。我相信提取的数据具有唯一标识符。 【参考方案1】:

一般而言,您可以说“如果我在数据存储中有任何货币条目,请不要添加更多”。这可以通过在第一次导入时添加一个使用默认值的标志或类似的东西来完成,但更好的选择是检查数据存储以查看它是否有任何货币条目。为此,请为currencyEntity 创建一个获取请求并使用countForFetchRequest:error:,然后再继续使用for currency in currencies 。如果计数大于零,那么您应该返回而不是处理循环。

为了提高效率,实际上应该在您下载和处理 JSON 之前进行此检查...

【讨论】:

该项目将读取我包含在 NSBundle 中的 json。如果我实施您提出的解决方案,是否会对应用的性能产生重大影响? 下载会是最大的成本,但如果你已经在数据存储中,你仍然不需要读入和处理它 好的,我会在添加任何新条目之前尝试检查货币条目。我会接受你的回答。 如果我在 json 文件中包含“GUID”并在第一次读取 json 文件后将 GUID 保存在 NSUserDefaults 中。每次构建时,代码都会检查 GUID 是否与之前读取的相同。如果相同,代码将跳过读取 json 并继续。假设将来我的 json 文件中有一些数据更改,我只需要更改为不同的 GUID,代码就会读取新的 json 文件。这应该更好吗? 是的,这是一个很好的解决方案和对未来的良好规划

以上是关于iOS - 数据保存一次到核心数据中的主要内容,如果未能解决你的问题,请参考以下文章

IOS/Xcode:将 Web 服务提要保存到核心数据中

ios:使用核心数据同时保存/更新多条记录

核心数据不在 iOS 5 中保留

在核心数据iOS中保存json数据

如何在核心数据iOS中获取每个实体的最后一个条目

iOS/Objective-C:在后台线程中保存到核心数据