CoreData:在保存操作后,相同的谓词(IN)返回不同的提取结果 [英] CoreData: Same predicate (IN) returns different fetched results after a Save operation
问题描述
巨大更新:
我创建了一个全新的项目来模仿这个问题,它一直出现!
这是我的数据模型:
任务
具有指向 Person的一对多关系
。
@interface Person:NSManagedObject
@property(nonatomic,retain)NSString * personId;
@property(nonatomic,retain)NSString * name;
@end
//
@class Person;
@interface任务:NSManagedObject
@property(nonatomic,retain)NSNumber * taskId;
@property(nonatomic,retain)NSSet * watchers;
@end
@interface任务(CoreDataGeneratedAccessors)
- (void)addWatchersObject:(Person *)value;
- (void)removeWatchersObject:(Person *)value;
- (void)addWatchers:(NSSet *)values;
- (void)removeWatchers:(NSSet *)values;
@end
现在,我创建两个人,p1& p2和两个任务,1001& 1002:
- (void)viewDidLoad
{
[super viewDidLoad];
//在加载视图之后执行任何其他设置,通常来自nib。
人* p1 = [self insertOrUpdatePerson:@111withName:@aaa];
Person * p2 = [self insertOrUpdatePerson:@222withName:@bbb];
[self insertOrUpdateTask:1001 withWatcher:p1];
[self insertOrUpdateTask:1001 withWatcher:p2];
[self insertOrUpdateTask:1002 withWatcher:p1];
[self insertOrUpdateTask:1002 withWatcher:p2];
NSArray * watchedTasks = nil;
watchedTasks = [self fetchTasksWatchedByPerson:p1]; // return 2 objects
NSLog(@watchedTasks:%@ \\\
,watchedTasks);
[self saveContext];
watchedTasks = [self fetchTasksWatchedByPerson:p1]; // return 1 objects
NSLog(@watchedTasks:%@ \\\
,watchedTasks);
NSArray * allTasks = [self fetchAllTasks]; // return 2 objects
NSLog(@allTasks:%@ \\\
,watchedTasks);
}
并且日志如下。 请注意,watchedTasks的第二个输出只有一个对象!
打印watchedTasks的描述:
< __ NSArrayI 0x8d5aff0>(
< Task:0x8d5b240>(entity:Task; id:0x8d5b3e0< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Task / p2& :{
taskId = 1002;
watchers =(
0x8d57f80< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Person / p2>,
0x8d56070< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Person / p1"
);
}),
< Task:0x8d59d10& entity:task; id:0x8d59420< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Task / p1> ;; data:{
taskId = 1001;
watchers = $ b0x8d57f80< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Person / p2>,
0x8d56070< x-coredata:// 706EB8CA-ACE7-48DB-89E1- 7CCFCDD41DA4 / Person / p1>
);
})
)
打印updateObjects的描述:
< __ NSArrayI 0x8e41880>(
< Task:0x8d59d10> (entity:Task; id:0x8d59420< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Task / p1> ;; data:{
taskId = 1001;
watchers = b $ b0x8d57f80< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Person / p2>,
0x8d56070< x-coredata:// 706EB8CA-ACE7-48DB-89E1 -7CCFCDD41DA4 / Person / p1>
);
}),
< Task:0x8d5b240> (entity:Task; id:0x8d5b3e0< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Task / p2> ;; data:{
taskId = 1002;
watchers = b $ b0x8d57f80< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Person / p2>,
0x8d56070< x-coredata:// 706EB8CA-ACE7-48DB-89E1 -7CCFCDD41DA4 / Person / p1>
);
}),
< Person:0x8d56cc0> (entity:Person; id:0x8d56070< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/ Person / p1> ;; data:{
name = aaa;
personId = 111;
}),
< Person:0x8d57be0> (entity:Person; id:0x8d57f80< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/ Person / p2> ;; data:{
name = bbb;
personId = 222;
})
)
打印watchedTasks的描述:
< _PFArray 0x8f57da0>(
< Task:0x8d5b240>(entity:Task; id :0x8d5b3e0< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Task / p2> ;; data:{
taskId = 1002;
watchers =(
0x8d57f80< ; x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Person / p2>,
0x8d56070< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Person / p1> ;
);
})
)
打印allTasks的描述:
< _PFArray 0x8e44b30>(
< 0x8d59d10>(entity:Task; id:0x8d59420< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Task / p1> ;; data:{
taskId = 1001;
watchers = (
0x8d57f80< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Person / p2>,
0x8d56070< x-coredata:// 706EB8CA-ACE7-48DB -89E1-7CCFCDD41DA4 / Person / p1>
);
}),
< Task:0x8d5b240> (entity:Task; id:0x8d5b3e0< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Task / p2> ;; data:{
taskId = 1002;
watchers = b $ b0x8d57f80< x-coredata:// 706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4 / Person / p2>,
0x8d56070< x-coredata:// 706EB8CA-ACE7-48DB-89E1 -7CCFCDD41DA4 / Person / p1>
);
})
)
(lldb)
所以我打开.sqlite文件看看到底是什么。
我惊讶的是,
watchers
在Person
表中,不是在中间/映射Task2Person
表中。我记得一旦关系存在于中间表中。
然后,
watchers
人
表只包含一个值,而不是集合或数组!- (void)viewDidLoad
{
[super viewDidLoad];
//在加载视图之后执行任何其他设置,通常来自nib。
NSArray * watchedTasks = nil;
人* p1 = [self insertOrUpdatePerson:@111withName:@aaa];
Person * p2 = [self insertOrUpdatePerson:@222withName:@bbb];
watchedTasks = [self fetchTasksWatchedByPerson:p1]; // return 1 object
任务* t1 = [self insertOrUpdateTask:1001 withWatcher:p1]; // update watchers in the memory
[self insertOrUpdateTask:1001 withWatcher:p2];
任务* t2 = [self insertOrUpdateTask:1002 withWatcher:p1];
[self insertOrUpdateTask:1002 withWatcher:p2];
watchedTasks = [self fetchTasksWatchedByPerson:p1]; // return 2 objects
[self saveContext];
watchedTasks = [self fetchTasksWatchedByPerson:p1]; // return 1 object
因此我发现在启动应用程序并从数据库中读取任务后文件,只返回1个对象。
当我更新任务的
watchers
信息时,可以抓取两个对象。
最后在保存上下文之后,只有一个对象。
- 以下的旧信息
我有以下代码:
NSArray * existedTasks = [[TaskBizDB sharedInstance] fetchTasksWatchedByMeOfProject:projectId];
[context save:& error];
existedTasks = [[TaskBizDB sharedInstance] fetchTasksWatchedByMeOfProject:projectId];
NSArray * allTasks = [[TaskBizDB sharedInstance] fetchTasksOfProject:projectId];
- 第一行返回两个对象;
- 第二行保存上下文;
- 第三行返回只有一个对象
- 最后一行返回6个对象,包含在第一行返回的两个对象
。
fetch接口的工作原理如下:
WXModel * model = [WXModel modelWithEntity:NSStringFromClass([WQPKTeamTask class])];
NSPredicate * predicate = [NSPredicate predicateWithFormat:@(%@ IN personWatchers)AND(projectId ==%d),currentLoginUser,projectId];
[model setPredicate:predicate];
NSArray * fetchedTasks = [model fetch];
if(fetchedTasks.count == 0)return nil;
return fetchedTasks;让我困惑的是,使用相同的获取请求,为什么在保存后返回不同的结果?
这里有更多细节:
在第一行返回的两个对象是:
< WQPKTeamTask:0x1b92fcc0> (实体:WQPKTeamTask; id:0x1b9300f0 ; data:{
projectId = 372004;
taskId = 338001;
personWatchers =(
0xf0bf440< x-coredata:// CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5 / WWPerson / p1>
);
}
< WQPKTeamTask:0xf3f6130>(实体:WQPKTeamTask; id:0xf3cb8d0 ; data:{
projectId = 372004;
taskId = 340006;
personWatchers =(
0xf0bf440< x-coredata:// CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5 / WWPerson / p1>
);
}
在第三行返回的唯一一个对象是: p>
< WQPKTeamTask:0x1b92fcc0>(实体:WQPKTeamTask; id:0x1b9300f0< x-coredata:// CFFD3F8B-E613-4DE8- 85AA-4D6DD08E88C5 / WQPKTeamTask / p9> ;; data:{
projectId = 372004;
taskId = 338001;
personWatchers =(
0xf0bf440< x-coredata:// CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5 / WWPerson / p1>
);
}
打印allTasks的说明:
< _PFArray 0xf30b9a0>(
< WQPKTeamTask:0xf3ab9d0>(entity:WQPKTeamTask; id:0xf3cda40< x-coredata:// CFFD3F8B-E613-4DE8 -85AA-4D6DD08E88C5 / WQPKTeamTask / p6>; data:< fault>),
< WQPKTeamTask:0xf315720>(entity:WQPKTeamTask; id:0xf3c23a0 < WQPKTeamTask:0xf3a1ed0>(实体:WQPKTeamTask; id:0xf3cda30 < WQPKTeamTask:0x1b92fcc0>(entity:WQPKTeamTask; id:0x1b9300f0 projectId = 372004;
taskId = 338001;
personWatchers =(
0xf0bf440< x-coredata:// CFFD3F8B-E613 -4DE8-85AA-4D6DD08E88C5 / WWPerson / p1>
);
}),
< WQPKTeamTask:0xf325e50& (实体:WQPKTeamTask; id:0xf343820< x-coredata:// CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5 / WQPKTeamTask / p10>; data:< fault>),
< WQPKTeamTask:0xf3f6130& (实体:WQPKTeamTask; id:0xf3cb8d0 ; data:{
projectId = 372004;
taskId = 340006;
personWatchers =(
0xf0bf440< x-coredata:// CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5 / WWPerson / p1>
);
})
)
UPDATE 1
如果我调用 fetchTasksWatchedByMeOfProject:
中的同一个界面:
#pragma mark - NSFetchedResultsController委托
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
UPDATE 2
$ b b
我试过:
NSPredicate * predicate = [NSPredicate predicateWithFormat:@(ANY personWatchers ==%@)AND(projectId ==%d),currentLoginUser,projectId];
NSPredicate * predicate = [NSPredicate predicateWithFormat:@(ANY personWatchers.personId ==%@)AND(projectId ==%d),currentLoginUserId,projectId];
仍然有同样的结果。
3
我已检查过 save:&错误
,错误是nil。
解决方案今天我和我的队友一起想出了这个问题。
例如任务
有一对多关系 watchers
到 Person
,但 Person
没有与 Task
关系字段 watchers
将放在 Person
表中,而不是中间/映射表。
在此条件下,我将 Person p1添加到 Task
t1's watchers
会将观察者
更新为 1
然后,将 Person
p1添加到 Person
表。
任务
t2, watchers
字段将更新为 2
如下:
/ p>
因此, Person
只能指向一个 Task
!
通过从 Person
添加一个反向关系到任务
可以绕过这个问题。
HUGE UPDATE:
I create a totally new project to mimic the problem, it does appear all the time!
Here is my data model:
Task
has a to-many relationship pointing to Person
.
@interface Person : NSManagedObject
@property (nonatomic, retain) NSString * personId;
@property (nonatomic, retain) NSString * name;
@end
//
@class Person;
@interface Task : NSManagedObject
@property (nonatomic, retain) NSNumber * taskId;
@property (nonatomic, retain) NSSet *watchers;
@end
@interface Task (CoreDataGeneratedAccessors)
- (void)addWatchersObject:(Person *)value;
- (void)removeWatchersObject:(Person *)value;
- (void)addWatchers:(NSSet *)values;
- (void)removeWatchers:(NSSet *)values;
@end
Now, I create two persons, p1 & p2, and two tasks, 1001 & 1002:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
Person *p1 = [self insertOrUpdatePerson:@"111" withName:@"aaa"];
Person *p2 = [self insertOrUpdatePerson:@"222" withName:@"bbb"];
[self insertOrUpdateTask:1001 withWatcher:p1];
[self insertOrUpdateTask:1001 withWatcher:p2];
[self insertOrUpdateTask:1002 withWatcher:p1];
[self insertOrUpdateTask:1002 withWatcher:p2];
NSArray *watchedTasks = nil;
watchedTasks = [self fetchTasksWatchedByPerson:p1]; // return 2 objects
NSLog(@"watchedTasks : %@\n", watchedTasks);
[self saveContext];
watchedTasks = [self fetchTasksWatchedByPerson:p1]; // return 1 objects
NSLog(@"watchedTasks : %@\n", watchedTasks);
NSArray *allTasks = [self fetchAllTasks]; // return 2 objects
NSLog(@"allTasks : %@\n", watchedTasks);
}
And the log follows. Notice that the second output of watchedTasks has only one object!
Printing description of watchedTasks:
<__NSArrayI 0x8d5aff0>(
<Task: 0x8d5b240> (entity: Task; id: 0x8d5b3e0 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Task/p2> ; data: {
taskId = 1002;
watchers = (
"0x8d57f80 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p2>",
"0x8d56070 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p1>"
);
}),
<Task: 0x8d59d10> (entity: Task; id: 0x8d59420 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Task/p1> ; data: {
taskId = 1001;
watchers = (
"0x8d57f80 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p2>",
"0x8d56070 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p1>"
);
})
)
Printing description of updateObjects:
<__NSArrayI 0x8e41880>(
<Task: 0x8d59d10> (entity: Task; id: 0x8d59420 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Task/p1> ; data: {
taskId = 1001;
watchers = (
"0x8d57f80 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p2>",
"0x8d56070 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p1>"
);
}),
<Task: 0x8d5b240> (entity: Task; id: 0x8d5b3e0 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Task/p2> ; data: {
taskId = 1002;
watchers = (
"0x8d57f80 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p2>",
"0x8d56070 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p1>"
);
}),
<Person: 0x8d56cc0> (entity: Person; id: 0x8d56070 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p1> ; data: {
name = aaa;
personId = 111;
}),
<Person: 0x8d57be0> (entity: Person; id: 0x8d57f80 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p2> ; data: {
name = bbb;
personId = 222;
})
)
Printing description of watchedTasks:
<_PFArray 0x8f57da0>(
<Task: 0x8d5b240> (entity: Task; id: 0x8d5b3e0 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Task/p2> ; data: {
taskId = 1002;
watchers = (
"0x8d57f80 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p2>",
"0x8d56070 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p1>"
);
})
)
Printing description of allTasks:
<_PFArray 0x8e44b30>(
<Task: 0x8d59d10> (entity: Task; id: 0x8d59420 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Task/p1> ; data: {
taskId = 1001;
watchers = (
"0x8d57f80 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p2>",
"0x8d56070 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p1>"
);
}),
<Task: 0x8d5b240> (entity: Task; id: 0x8d5b3e0 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Task/p2> ; data: {
taskId = 1002;
watchers = (
"0x8d57f80 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p2>",
"0x8d56070 <x-coredata://706EB8CA-ACE7-48DB-89E1-7CCFCDD41DA4/Person/p1>"
);
})
)
(lldb)
So I open the .sqlite file to see what exactly in.
What surprise me first is that watchers
is in the Person
table, not in a middle/mapping Task2Person
table. I remember that once the relationship exists in a middle table.
Then, the watchers
field in the Person
table contains only one value, not a set or array!
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSArray *watchedTasks = nil;
Person *p1 = [self insertOrUpdatePerson:@"111" withName:@"aaa"];
Person *p2 = [self insertOrUpdatePerson:@"222" withName:@"bbb"];
watchedTasks = [self fetchTasksWatchedByPerson:p1]; // return 1 object
Task *t1 = [self insertOrUpdateTask:1001 withWatcher:p1]; // update watchers in the memory
[self insertOrUpdateTask:1001 withWatcher:p2];
Task *t2 = [self insertOrUpdateTask:1002 withWatcher:p1];
[self insertOrUpdateTask:1002 withWatcher:p2];
watchedTasks = [self fetchTasksWatchedByPerson:p1]; // return 2 objects
[self saveContext];
watchedTasks = [self fetchTasksWatchedByPerson:p1]; // return 1 object
So I found that after I launch the App and read the tasks from the db file, only 1 object is returned.
When I update the watchers
information for the tasks, 2 objects can be fetched.
Finally after I save the context, only 1 object again.
Just Ignore This
- Old Information Below
I have code below:
NSArray *existedTasks = [[TaskBizDB sharedInstance] fetchTasksWatchedByMeOfProject:projectId];
[context save:&error];
existedTasks = [[TaskBizDB sharedInstance] fetchTasksWatchedByMeOfProject:projectId];
NSArray *allTasks = [[TaskBizDB sharedInstance] fetchTasksOfProject:projectId];
- First line returns two objects;
- Second line save the context;
- Third line returns just one object, which is contained in the 'two objects' above;
- And the last line returns 6 objects, containing the 'two objects'
returned at the first line.
The fetch interface works like below:
WXModel *model = [WXModel modelWithEntity:NSStringFromClass([WQPKTeamTask class])];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(%@ IN personWatchers) AND (projectId == %d)", currentLoginUser, projectId];
[model setPredicate:predicate];
NSArray *fetchedTasks = [model fetch];
if (fetchedTasks.count == 0) return nil;
return fetchedTasks;
What confused me is that, with the same fetch request, why return different results just after a save?
Here comes more detail:
The 'two objects' returned at the first line are:
<WQPKTeamTask: 0x1b92fcc0> (entity: WQPKTeamTask; id: 0x1b9300f0 <x-coredata://CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5/WQPKTeamTask/p9> ; data: {
projectId = 372004;
taskId = 338001;
personWatchers = (
"0xf0bf440 <x-coredata://CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5/WWPerson/p1>"
);
}
<WQPKTeamTask: 0xf3f6130> (entity: WQPKTeamTask; id: 0xf3cb8d0 <x-coredata://CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5/WQPKTeamTask/p11> ; data: {
projectId = 372004;
taskId = 340006;
personWatchers = (
"0xf0bf440 <x-coredata://CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5/WWPerson/p1>"
);
}
And the only one object returned at third line is:
<WQPKTeamTask: 0x1b92fcc0> (entity: WQPKTeamTask; id: 0x1b9300f0 <x-coredata://CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5/WQPKTeamTask/p9> ; data: {
projectId = 372004;
taskId = 338001;
personWatchers = (
"0xf0bf440 <x-coredata://CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5/WWPerson/p1>"
);
}
Printing description of allTasks:
<_PFArray 0xf30b9a0>(
<WQPKTeamTask: 0xf3ab9d0> (entity: WQPKTeamTask; id: 0xf3cda40 <x-coredata://CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5/WQPKTeamTask/p6> ; data: <fault>),
<WQPKTeamTask: 0xf315720> (entity: WQPKTeamTask; id: 0xf3c23a0 <x-coredata://CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5/WQPKTeamTask/p7> ; data: <fault>),
<WQPKTeamTask: 0xf3a1ed0> (entity: WQPKTeamTask; id: 0xf3cda30 <x-coredata://CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5/WQPKTeamTask/p8> ; data: <fault>),
<WQPKTeamTask: 0x1b92fcc0> (entity: WQPKTeamTask; id: 0x1b9300f0 <x-coredata://CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5/WQPKTeamTask/p9> ; data: {
projectId = 372004;
taskId = 338001;
personWatchers = (
"0xf0bf440 <x-coredata://CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5/WWPerson/p1>"
);
}),
<WQPKTeamTask: 0xf325e50> (entity: WQPKTeamTask; id: 0xf343820 <x-coredata://CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5/WQPKTeamTask/p10> ; data: <fault>),
<WQPKTeamTask: 0xf3f6130> (entity: WQPKTeamTask; id: 0xf3cb8d0 <x-coredata://CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5/WQPKTeamTask/p11> ; data: {
projectId = 372004;
taskId = 340006;
personWatchers = (
"0xf0bf440 <x-coredata://CFFD3F8B-E613-4DE8-85AA-4D6DD08E88C5/WWPerson/p1>"
);
})
)
UPDATE 1
If I call the same interface fetchTasksWatchedByMeOfProject:
in:
#pragma mark - NSFetchedResultsController Delegate
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
I will get 'two objects' as well.
UPDATE 2
I've tried:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(ANY personWatchers == %@) AND (projectId == %d)", currentLoginUser, projectId];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(ANY personWatchers.personId == %@) AND (projectId == %d)", currentLoginUserId, projectId];
Still the same result.
UPDATE 3
I've checked the save:&error
, error is nil.
解决方案 I've figured out this problem today with my teammates.
If you create a to-many relationship without inverse relationship, for example, Task
has a to-many relationship watchers
to Person
, but Person
doesn't have a inverse one to Task
, then the relationship field watchers
will be put in the Person
table instead of a middle/mapping table.
Under this condition, my adding a Person
p1 into the Task
t1's watchers
will update the watchers
filed to 1
in the Person
table.
Then, add Person
p1 to the Task
t2 as well, the watchers
field will be update to 2
like below:
So, one Person
can only point to one Task
!
By adding a inverse relationship from Person
to Task
can walk around this problem.
这篇关于CoreData:在保存操作后,相同的谓词(IN)返回不同的提取结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!