【问题标题】:Fetching data using Core Data使用 Core Data 获取数据
【发布时间】:2014-02-21 22:35:26
【问题描述】:

我在互联网上搜索了很多,但找不到我要找的东西。

我有这个模型,它可能有很多用户。所以我有一个名为User 的实体。用户拥有NSSet 的记录。我想从给定用户那里获取记录。我正在尝试这样做,但它仍会返回所有用户的记录。

NSManagedObjectContext *context = _backgroundContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Record"
                                                  inManagedObjectContext:context];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(date >= %@)",date];
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"User = %@",currentUser];

NSPredicate *predicates = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:predicate,predicate1, nil]];
[fetchRequest setPredicate:predicates];

[fetchRequest setPredicate:predicate];
[fetchRequest setEntity:entity];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];

我知道这应该不难,但我找不到它是什么,我希望你们中的一些人能提供帮助。提前致谢!

编辑:

正如我所说,我有一个实体 User,它具有:

NSString name,
int age,
NSSet records, ...

Record有自己的属性如:

NSDate date,
NSString name,
NSString event, 
...

我想形成一个获取请求以仅从特定用户获取记录。而且我不知道该怎么做,因为我要从每个用户那里获取所有记录。

记录具有多对多关系。我可以获取 currentUser.records 之类的记录,但我无法使用 record.User 获取用户。

【问题讨论】:

  • 你能不能简单点我的意思是你使用任何关系?如果是,请提供简短的说明。
  • 结帐 MagicalRecord (github.com/magicalpanda/MagicalRecord)。这将使使用 Core Data 变得更加容易......

标签: objective-c ios core-data nspredicate nsfetchrequest


【解决方案1】:

我假设您的模型大致如下所示,即记录关系具有称为用户的反向关系:

重要的是,这种关系是反向关系,否则 Core Data 不会自动维护它。然后,您可以在给定日期/之后查询给定用户的所有记录,如下所示:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Record"];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"user = %@ AND (date >= %@)", currentUser, date];

NSError *error = nil;
NSArray *records = [_backgroundContext executeFetchRequest:fetchRequest error:&error];

NSLog(@"records: %@", records);

我已将您的代码重写为更紧凑,但重要的变化是这将一次性创建查询。

【讨论】:

    【解决方案2】:

    错误在这里:

    [fetchRequest setPredicate:predicates];
    [fetchRequest setPredicate:predicate];
    

    设置复合谓词后,您只用date 的谓词覆盖它。您可能想删除第二行。

    编辑:获取请求要求您定义了从 RecordUser 的反向关系 user,并在谓词中使用此关系的确切名称。

    另一种解决方案是使用从UserRecord 的“转发”关系并过滤结果:

    NSSet *records = [currentUser.records filteredSetUsingPredicate:predicates];
    

    或者,如果您更喜欢数组

    NSArray *records = [[currentUser.records allObjects] filteredArrayUsingPredicate:predicates];
    

    【讨论】:

    • 我太傻了!谢谢你,但这并不能解决我的问题:(我收到一个错误“keypath User not found in entity”。
    • @Lukas: 从RecordUser 的关系叫什么?也许user(小写)?如果这没有帮助,请显示使用Record 实体的定义。
    • 查看我的编辑,我无法获得像 record.User 这样的用户,我只能通过使用 currentUser.records 来获得记录。我可以在这个集合中运行一个循环,但它看起来很讨厌。所以我正在寻找更好的解决方案。
    • @Lukas:您必须将user 定义为从RecordUser 的关系(与records 的反比关系)。然后谓词 "user = %@", currentUser 应该可以工作。
    • @Lukas:请注意:currentUser.records 是一个明智的选择。您可以使用 filteredSetUsingPredicate: 过滤 - 无需循环!
    【解决方案3】:

    正如 Martin R 所说,您正在替换您的谓词。 正如他还提到的,用户属性应该是小写的,因为我很确定核心数据会强制执行这一点。如果您尝试使用大写字母创建关系,它应该会给您一个错误,所以请尝试

    NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"user = %@",currentUser];
    

    相反。显然,如果您的模型没有为用户定义属性,那么它也不会起作用,您需要将其更改为您的模型实际具有的任何属性,但否则应该可以。

    编辑:

    尝试在模型中添加反向关系。所以你的结构看起来像:

    用户

    NSString name,
    int age,
    NSSet records, ...
    

    记录

    NSDate date,
    NSString name,
    NSString event, 
    User user,
    ...
    

    然后每次创建新记录以及将记录添加到用户记录集时,也要在记录对象上设置用户。这将使获取记录变得更加容易,并且还允许核心数据保持数据完整性:

    "You should typically model relationships in both directions, and specify the inverse 
    relationships appropriately. Core Data uses this information to ensure the consistency of the 
    object graph if a change is made"
    

    (Core Data programming guide)

    设置完成后,您应该可以通过调用record.user轻松获取记录用户

    如果您需要多个用户来处理多个记录,则只需将关系设置为一对多关系,并将User user 属性更改为NSSet user

    如果您不想对模型进行这么多的更改,那么我对您的问题感到有些困惑。你说你想获取给定用户的记录?如果是这样,那么您为什么不简单地致电user.records,因为您已经定义了这种关系?不需要整个获取请求,让核心数据为您管理那个。

    如果您想根据日期过滤结果记录,您可以自己将谓词应用于结果数组,同样无需获取请求。

    【讨论】:

    • 那行不通,但感谢您的帮助!正如我所说,我无法从 record.user 获取用户:/ 它只能像 currentUser.records 一样以相反的方式工作,这将返回该用户的所有记录。
    • 您只需要添加一个反向关系(Apple 建议这样做以确保数据一致性),因此在您记录模型时,添加用户关系(一对多)或用户(多对多)许多)。然后当你创建记录时,只需设置用户或添加用户,你应该可以做你想做的事情:)
    【解决方案4】:

    我找到了我搜索的内容!我只需要使用这个来形成一个谓词

    NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"SELF = %@",delegate.currentUser]; 
    

    编辑

    好吧,看来我错了:/这似乎有效。

    【讨论】:

    • 很高兴您解决了它。但是您应该仔细检查您的解决方案,因为对先生来说,这似乎与您的问题有所不同。
    • @MartinR 你说得对!这只似乎有效,因为我只测试了几条记录。伤心:/
    猜你喜欢
    • 2018-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-29
    • 2014-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多