使用 Core Data 一对多关系从 JSON 数组填充 sqlite 数据库

Posted

技术标签:

【中文标题】使用 Core Data 一对多关系从 JSON 数组填充 sqlite 数据库【英文标题】:Populate sqlite database from JSON array with Core Data one-to-many relationship 【发布时间】:2013-02-26 02:26:51 【问题描述】:

我正在尝试从 JSON 文件中读取数据并将其存储到 sqlite。我正在获取“简单”数据,但我不知道如何将一对多关系项从我的数组中获取到 sqlite。

这是我的数据模型:

(抱歉,他们不让我在这里截屏...所以这里是数据模型的描述:)

    Entity: SeasonInfo 
    Attributes:
    year
    coach
    wins
    losses
    ties
        Relationship: players
        Destination: PlayerInfo
        Inverse seasonInfo

    Entity: PlayerInfo
    Attributes:
    name
    number
       Relationship: seasonInfo
       Destination: SeasonInfo
       Inverse: players

这是我的 JSON:

    [
        "year": 2012, "wins": 8,  "losses": 8, "ties": 0, "coach": "Garrett",
          "players": [  "name": "Tony Romo",  "number": 9,
                       "name": "Dez Bryant",   "number": 88 ],
       ,
        "year": 2011, "wins": 8,  "losses": 8, "ties": 0, "coach": "Garrett",
         "players": [  "name": "DeMarcu Ware",  "number": 94,
                        "name": "Felix Jones ",  "number": 28,
                        "name": "Miles Austin",  "number": 19 ],
        ,
         "year": 2010, "wins": 6,  "losses": 10, "ties": 0, "coach": "Garrett/Phillips",
          "players": [  "name": "Sean Lee",      "number": 50,
                        "name": "Jason Witten",  "number": 82 ],
        
     ]

这是我的代码:

    // Load JSON data into Array
    NSError* err = nil;
    NSString* dataPath = [[NSBundle mainBundle] pathForResource:@"CowboySeason" ofType:@"json"];
    NSArray* cowboySeasonsArray = [NSJSONSerialization JSONObjectWithData:[NSData dataWithContentsOfFile:dataPath]
                                                                  options:kNilOptions
                                                                    error:&err];
    NSLog(@"Imported Seasons: %@", cowboySeasonsArray);


    // Export data from the array into the database

    // Store the SeasonInfo 
    [cowboySeasonsArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) 
        SeasonInfo *seasonInfo = [NSEntityDescription
                                          insertNewObjectForEntityForName:@"SeasonInfo"
                                          inManagedObjectContext:context];

        seasonInfo.year = [obj objectForKey:@"year"];
        seasonInfo.wins = [obj objectForKey:@"wins"];
        seasonInfo.losses = [obj objectForKey:@"losses"];
        seasonInfo.ties = [obj objectForKey:@"ties"];
        seasonInfo.coach = [obj objectForKey:@"coach"];

        seasonInfo.players = [obj objectForKey:@"players"];

        NSError *error;
        if (![context save:&error]) 
            NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
        
    ];

cowboySeasonArray 在日志中是这样的:

    2013-02-25 20:39:05.025 SeasonTestLoader[369:503] Imported Seasons: (
    
    coach = Garrett;
    losses = 8;
    players =         (
                    
            name = "Tony Romo";
            number = 9;
        ,
                    
            name = "Dez Bryant";
            number = 88;
        
    );
    ties = 0;
    wins = 8;
    year = 2012;
,
    
    coach = Garrett;
    losses = 8;
    players =         (
                    
            name = "DeMarcu Ware";
            number = 94;
        ,
                    
            name = "Felix Jones ";
            number = 28;
        ,
                    
            name = "Miles Austin";
            number = 19;
        
    );
    ties = 0;
    wins = 8;
    year = 2011;
,
    
    coach = "Garrett/Phillips";
    losses = 10;
    players =         (
                    
            name = "Sean Lee";
            number = 50;
        ,
                    
            name = "Jason Witten";
            number = 82;
        
    );
    ties = 0;
    wins = 6;
    year = 2010;

)

所以它看起来像 JSON 解析器工作......但我无法弄清楚如何将一对多 PlayerInfo 放入 sqlite。

我知道 seasonInfo.players = [obj objectForKey:@"players"];行错了……只是不知道在这里做什么。

温柔点...我是 ios 新手。

【问题讨论】:

【参考方案1】:

看起来你已经让团队的“外循环”工作了,现在你只需要在每个团队中添加一个玩家的“内循环”。

从您用于创建团队的代码开始,并在您的循环中:

// Other stuff from your code here, omitted for brevity
seasonInfo.ties = [obj objectForKey:@"ties"];
seasonInfo.coach = [obj objectForKey:@"coach"];

// Loop through each player, creating a new PlayerInfo entity for each one:
NSArray *playerArray = [obj objectForKey:@"players"]
[playerArray enumerateObjectsUsingBlock:^(id playerObj, NSUInteger playerIdx, BOOL *playerStop) 
    PlayerInfo *playerInfo = [NSEntityDescription
                                      insertNewObjectForEntityForName:@"PlayerInfo"
                                      inManagedObjectContext:context];

    playerInfo.seasonInfo = seasonInfo;
    playerInfo.name = [playerObj objectForKey:@"name"];
    playerInfo.number = [playerObj objectForKey:@"number"];
];

NSError *error;
if (![context save:&error]) 
    NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);

因为你在 PlayerInfo 和 SeasonInfo 之间设置了反向关系,你可以从关系的任何一端建立连接,另一端将被自动处理。在这种情况下,您将创建新的 PlayerInfo 实体,并通过设置每个实体的 seasonInfo 值,将填充 SeasonInfo 端的一对多关系。

您还可以将单个 PlayerInfo 对象添加到 SeasonInfo 的玩家关系集中,但我发现这比仅将多个实体中的每个实体的关系添加回一个更令人困惑。

【讨论】:

以上是关于使用 Core Data 一对多关系从 JSON 数组填充 sqlite 数据库的主要内容,如果未能解决你的问题,请参考以下文章

RestKit 0.2 映射 Core Data <--> JSON 与一对多关系

在 Swift Core Data 中从一对多关系中获取对象

Core Data 使用多个上下文中的新对象从后台线程订购一对多关系保存

如何使用 JSON 预加载一对多核心数据关系

Core Data 获取一对多关系的数据

Core Data addObject 一对多关系