2017-04-15 72 views
0

好的,我已经读过苹果Core Data Guide。我也在网上看,但只发现大约2年前的帖子。所以我不知道有多少关系工作。我正在使用核心数据构建应用程序。该应用程序有3个实体口袋妖怪类型能力。口袋妖怪可以有一个或多个类型,所以我将关系设置为多对多。一个类型可以有多个与它关联的口袋妖怪,所以我也应该将关系设置为多对多,但我不明白多对多的关系。能力同样如此。这就是我的数据模型的样子。还有另外两个实体,但我现在不太在意这些。多对多关系如何运作。

enter image description here

这是我用来解析以下API功能。它抓住了前20名的口袋妖怪保存名称,并使用URL来获取更多关于该口袋妖怪的信息。所以我增加了另一项任务,为该口袋妖怪增加了类型和能力。

private func loadPokemon(url: String) { 
    let context = coreData.persistentContainer.viewContext 
    let request = URLRequest(url: URL(string: url)!) 
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in 
     if error != nil { 
      print(error!) 
     } 

     do { 
      let jsonResults = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary 
      let pokemonArray = jsonResults.value(forKey: "results") as! [[String: Any]] 

      for pokemonData in pokemonArray { 

       guard let name = pokemonData["name"] as? String else { 
        return 
       } 

       guard let pokemonInfoURL = pokemonData["url"] as? String else { 
        return 
       } 

       let pokemon = Pokemon(context: context) 
       pokemon.name = name 
       print(1) 

       self.pokemonMoreInfo(for: pokemon, url: pokemonInfoURL, context: context) 

      } 
     } 
     catch let err { 
      print(err.localizedDescription) 
     } 
    } 
    task.resume() 
} 

private func pokemonMoreInfo(for pokemon: Pokemon, url: String, context: NSManagedObjectContext) { 
    let request = URLRequest(url: URL(string: url)!) 
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in 
     if error != nil { 
      print(error!) 
     } 

     do { 
      let jsonResults = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary 


      //MARK: Pokemon Abilities 
      if let abilityArray = jsonResults.value(forKey: "abilities") as? [[String: Any]] { 
       let abilities = pokemon.ability?.mutableCopy() as! NSMutableSet 

       for abilityData in abilityArray { 

        guard let abilityDic = abilityData["ability"] as? NSDictionary else { 
         return 
        } 
        let name = abilityDic.value(forKey: "name") as! String 

        guard let isHidden = abilityData["is_hidden"] as? Bool else { 
         return 
        } 

        guard let slot = abilityData["slot"] as? Int16 else { 
         return 
        } 

        let ability = Ability(context: context) 
        ability.name = name 
        ability.isHidden = isHidden 
        ability.slot = slot 

        abilities.add(ability) 
        pokemon.addToAbility(abilities) 
       } 
      } 

      //MARK: Pokemon Type 
      if let typeArray = jsonResults.value(forKey: "types") as? [[String: Any]] { 
       let types = pokemon.type?.mutableCopy() as! NSMutableSet 

       for typeData in typeArray { 

        guard let typeDic = typeData["type"] as? NSDictionary else { 
         return 
        } 
        let name = typeDic.value(forKey: "name") as! String 

        guard let slot = typeData["slot"] as? Int16 else { 
         return 
        } 

        let type = Type(context: context) 
        type.name = name 
        type.slot = slot 

        types.add(type) 
        pokemon.addToType(types) 
       } 
      } 
     } 
     catch let err { 
      print(err.localizedDescription) 
     } 
     self.coreData.saveContext() 
    } 
    task.resume() 
} 

我正在使用这个名为SQLight只读的应用程序。能力和类型与正确的宠物小精灵相匹配。这些是关于我的SQLight如何的截图。

enter image description here

我不知道,如果你们知道口袋妖怪,但喷火龙类是飞行,并有太阳能发电的能力大火。所以我知道我正确地保存了数据。但是我SQLight具有相同类型的重复就像同样适用于能力,但与之相关的正确口袋妖怪。这就是我完整的SQLight的样子。

enter image description here

不知道是否会继续与许多一对多的关系重复。所以我的问题是我会怎么用与口袋妖怪能力多对一对多的关系。那么如何添加具有相同类型或相同能力的口袋妖怪。所以后来,我可以执行抓取,抓取所有具有类型火焰或相同能力的口袋妖怪。我不确定是否正确解释我的问题可能会有点混乱。

希望有任何帮助。 :)

+0

核心数据是一个对象持久化系统,而不是一个sql数据库。我建议你不要尝试分析底层的sql数据存储。只需将对象引用设置为Pokemon的'type'属性,并让CoreData更新引用即可。 – Paulw11

回答

0

编辑: 其实我下面写的是不正确的核心数据。(感谢您指出这一点在评论Paulw11。)从Core Data Guide

许多一对多的关系

您定义使用两个一对多关系的许多一对多的关系。第一对多关系从第一个实体(源实体)到第二个实体(目的地)。第二对多关系从第二个实体(原始目标实体)转到第一个实体(原始源实体)。然后你将每个设置为另一个的倒数。 (如果您有数据库管理后台,这会导致你的关注,也不用担心:如果你使用一个SQLite店,核心数据自动为您创建中间连接表)


老答案(核心数据不正确): 要在关系数据库中创建多对多关系,您必须添加一个辅助表。在你的情况下,你可以称它为PokemonWithType。它有两列,一个是口袋妖怪ID,另一个是Type ID。如果你想找到一个特定的口袋妖怪的所有类型,你只需要查询PokemonWithType中的所有条目与特定的口袋妖怪ID。如果你想找到所有具有特定类型的口袋妖怪,你只需要输入类型id即可。

+0

嘿本杰明,你能提供截图或示例代码吗?如果可以的话,将不胜感激。 :) –

+0

CoreData直接支持多对多关系。虽然它可以由SQLite支持,但它是一个对象持久性系统,而不是数据库。 – Paulw11

+0

是的。我纠正了我的答案。 @Luis - 你需要添加从能力到口袋妖怪以及从类型到口袋妖怪的一对多关系。然后应该出现所需的关系。抱歉,现在我无法提供屏幕截图。 –