CoreData:在保存操作后,相同的谓词(IN)返回不同的提取结果 [英] CoreData: Same predicate (IN) returns different fetched results after a Save operation

查看:427
本文介绍了CoreData:在保存操作后,相同的谓词(IN)返回不同的提取结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

巨大更新:



我创建了一个全新的项目来模仿这个问题,它一直出现!



这是我的数据模型:







任务具有指向 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 * allTask​​s = [self fetchAllTask​​s]; // return 2 objects
NSLog(@allTask​​s:%@ \\\
,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> ;
);
})


打印allTask​​s的描述:
< _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 * allTask​​s = [[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>
);
}

打印allTask​​s的说明:

 < _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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆