好的,我读过苹果Core Data Guide。我也在网上看,但大约2年前才找到帖子。所以我不知道有多少关系工作。我正在使用核心数据构建应用。该应用有3个实体 宠物小精灵 , 类型 , 能力 。口袋妖怪可以有1种或更多类型,所以我将关系设置为to-many。一个类型可以有多个与之关联的Pokemon,所以我也应该将关系设置为to-many但我不理解多对多关系。能力也是如此。这就是我的数据模型的样子。还有另外两个实体,但我现在并不关心这些实体。
这是我用来解析以下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 Read-Only的应用程序。能力和类型与正确的口袋妖怪相匹配。这些是关于我的SQLight外观的截图。
我不确定你们是否知道口袋妖怪,但是charizard类型是 fire 和 飞行 并具有 太阳能 和 blaze 的能力。所以我知道我正确地保存了数据。但是我的SQLight有类似的重复类型,如 fire , grass , 毒药 相同的功能,但与正确的口袋妖怪相关联。这就是我完整的SQLight的样子。
不确定它是否会继续与多对多关系重复。所以我的问题是我如何使用 宠物小精灵 与 类型 和 能力 即可。那么我如何添加具有相同类型或相同能力的口袋妖怪。所以后来,我可以执行一次抓取,抓住所有具有火力或相同能力的口袋妖怪。我不确定我是否正确解释了我的问题可能会有点混乱。
非常感谢任何帮助。 :)
答案 0 :(得分:0)
修改强> 实际上我在下面写的内容对于Core Data来说并不正确。 (感谢你在评论Paulw11中指出这一点。)来自Core Data Guide:
多对多关系
使用两对多关系定义多对多关系。第一个到多个关系从第一个实体(源实体)到第二个实体(目标)。第二对多关系从第二实体(原始目标实体)到第一实体(原始源实体)。然后将每个设置为另一个的倒数。 (如果您有数据库管理的背景,这引起您的关注,请不要担心:如果您使用SQLite存储,Core Data会自动为您创建中间连接表。)
旧答案(核心数据不正确): 要在关系数据库中创建多对多关系,您必须添加一个帮助程序表。在你的情况下,你可以称之为PokemonWithType。它有两列,一列用于Pokemon id,另一列用于Type id。如果你想找到一个特定口袋妖怪的所有类型,你只需要查询PokemonWithType中具有特定口袋妖怪id的所有条目。如果你想找到所有具有特定类型的口袋妖怪,你只需要使用类型ID。