【发布时间】:2016-02-20 11:02:34
【问题描述】:
在核心数据中,我有一个通过桥实体连接的关系
有问题的关系是卡 ->> 段 ->> 战士
- 一个
card有很多segments - 一个
segment有多个fighters一个 -
fighter可以出现在一个segment上
一个段(或 SegmentRow)附有一系列战斗机。
如下图所示;
应用程序当前的工作方式是,用户选择一名战斗机添加到分段行。一旦他们点击保存,分配到该行的分段行和战士将被保存。
但我不断收到关系错误;
非法尝试在对象之间建立“战士”关系 在不同的上下文中(来源 = 段 -- 名称:第 0 行,有 0 名战士 , 目的地 = 一些战士)'
一些注意事项:
卡片对象还不存在,这是因为需要先保存段;然后可以保存卡片对象。
所以我要保存的代码是这样的;
+ (void) saveSegments:(NSArray *)segments inContext:(NSManagedObjectContext *)context withCompletion:(void (^)(BOOL success, NSError *error))completion
{
int i = 0;
for (FCSegmentRow *row in segments) {
FCSegment *segment = [FCSegment MR_createEntityInContext:context];
segment.name = [NSString stringWithFormat:@"Row %lu", (unsigned long)i];
// Fighters
NSMutableSet *fighters = [NSMutableSet set];
for (FCFighter *fighter in row.fighters) {
if (fighter) {
[fighters addObject:fighter];
}
}
segment.fighters = [NSSet setWithSet:fighters];
i++;
}
[context MR_saveToPersistentStoreAndWait];
// Output
NSArray *allSegments = [self segmentsInContext:context error:nil];
for (FCSegment *segment in allSegments) {
NSLog(@"%@", [segment description]);
}
}
FCSegmentRow 只是一个带有 NSArray *fighters 的简单 NSObject;
在我的代码中,我尝试设置一个可变集并将战斗机添加到该集,然后将其保存到核心数据。
此外,我尝试将保存放在一个块中并等待完成;但这个问题继续发生。
这似乎是因为战斗机与我正在创建的片段处于不同的上下文中。
所以,我的问题是——我如何存储片段与其战士(关系)
编辑:战士是在哪里以及如何创建的?
参考问题
战斗机位于自己的页面(视图控制器)上,并拥有自己的托管对象上下文。
管理分段的页面允许用户从战斗机列表中进行选择;这将启动战斗机页面并等待完成块以“返回”所选战斗机。
战士数据来自 Firebase,并将其加载到核心数据中。
战士视图控制器就是这样配置的;
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = @"Pick Fighter";
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.context = [NSManagedObjectContext MR_context];
[self reloadData];
}
// ...
-(void) reloadData
{
self.fighterList = [FCFighter findFightersInContext:self.context];
[self.tableView reloadData];
}
如上所示,战士视图控制器有自己的上下文
编辑: 补充说明:
一张卡片由许多段组成,我称之为段行。
在“分段行视图控制器”上,每个表格单元格有 2 个按钮(一个分段有 2 个战斗机),用户可以按下任一按钮并触发战斗机页面,让用户选择所需的战斗机。
我尝试将与段行视图控制器中相同的上下文传递到战斗机页面,但发生的情况是,一旦我按下第二个按钮,它就会丢失第一个按钮的数据。
IE: 按下按钮 A - 选择一名战士 .. Joe Bloggs 按下按钮 B - 选择一名战士 .. 迈克·史密斯 当我返回分段行时;按下按钮A的战斗机消失;当我检查数据时它的(空)。
启动战士页面的代码如下;
UIStoryboard *mainStoryboard = [UIStoryboard mainStoryboard];
FCFightersTableViewController *vc = (FCFightersTableViewController *) [mainStoryboard instantiateViewControllerWithIdentifier:@"FCFightersTableViewController"];
vc.tableCellSelectable = YES;
vc.excludeFighters = [selectedFightersMutable copy];
//vc.context = self.context;
vc.completionBlock = ^(FCFightersTableViewController *vc, FCFighter *fighter) {
NSLog(@"Picked fighter - %@ (uuid: %@)", fighter.name, fighter.uuid);
[fightersInRow setObject:fighter atIndexedSubscript:fighterIdx];
segmentRow.fighters = [fightersInRow copy];
NSLog(@"selected fighter - %@ (uuid: %@)", fighter.name, fighter.uuid);
[fightersInRow setObject:fighter atIndexedSubscript:fighterIdx];
segmentRow.fighters = [fightersInRow copy];
[self.tableView beginUpdates];
[self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
[self.tableView endUpdates];
};
【问题讨论】:
-
在哪里以及如何创建战斗机对象?
-
你是对的,所以你需要告诉我们更多关于你的背景和战士来自哪里......
-
您好。战士在另一个页面上(视图控制器)。这个视图控制器有它自己的托管对象上下文。所以有3页。第一个是卡。二是段位管理,三是斗士。
-
因为页面 A 启动页面 B;是否需要传递 Page A 的托管对象上下文?
-
@cardigan 分段和战斗机必须在相同的上下文中才能在它们之间建立关系。除非您出于其他原因需要两个上下文,否则是的,只需将上下文从一个 VC 传递到下一个 VC。如果您确实需要单独的上下文,请传递 NSManagedObjectIDs 并在第二个上下文中重新获取您需要的任何对象。
标签: objective-c core-data nsmanagedobjectcontext