【问题标题】:CoreData's NSFetchrequest: Provide classname and propertynames moredynamicallyCoreData 的 NSFetchrequest:更动态地提供类名和属性名
【发布时间】:2011-06-24 12:31:43
【问题描述】:

在CoreData中,当你想查询一个对象时,你必须指定实体的名称和字符串中的属性名称,如下所示:

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

fetchRequest.entity = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:context];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"Name=%@ AND Forename=%@", name, vorname];

我不太喜欢这种方法,因为这样做,IDE 在重命名某个属性或重命名类名等场景中无法帮助我。

使用这个代码块,我通过自省获取类名,使我的调用更加动态:

NSString *classname = [[Person class] description];    
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

fetchRequest.entity = [NSEntityDescription entityForName:classname inManagedObjectContext:context];
fetchRequest.predicate = [NSPredicate predicateWithFormat:@"Name=%@ AND Forename=%@", name, vorname];

有没有办法以相同的方式获取属性的名称(名称和名字)? 我不知道如何动态处理属性。

你明白我的意思吗?如果有人能指出我正确的方向,我会很高兴。

【问题讨论】:

    标签: objective-c ios core-data introspection


    【解决方案1】:

    我以这种方式在资源包中使用了 plist,基本上,创建一个 NSDictionary 将作为参数的键映射到手头对象上的属性名称,然后命名它MyClassname.plist 便于加载到内存中。不过,你必须为你想要的每一门课写一个。 (如果您更改属性名称,请编辑它们)

    不确定是否有更简单的方法。

    而且,IIRC,您可以这样插入键:

    [NSPredicate predicateWithFormat:@"%k=%@",[plist objectForKey:@"param1"],[personObject valueForKey:[plist objectForKey:@"param1"]]]
    

    【讨论】:

    • 感谢您的回答。在我看来,将包含属性名称的字符串作为方法参数传递是很常见的。我是 Objective-C 的新手,通常在 c# 中工作。使用 LINQ,您可以轻松定义查询,在其中按属性过滤元素。 IEnumerable<Person> result = allEntities.Where(p=> p.Name == name && p.Forename == forename);
    【解决方案2】:

    我不确定我是否看到 entityForName:[[Person class] description] 相对于 entityForName:@"Person" 的巨大优势(或者可能是 entityForName:PersonEntityName,其中 PersonEntityName 只是一个常数)。只要代表实体的类的名称与实体的名称相同,它就可以正常工作,但通常情况并非如此。对简单实体使用普通的旧 NSManagedObject 是很常见的,这显然与实体名称不匹配。

    同样,如果您正在创建获取请求,您感兴趣的属性的名称通常已经确定并且不太可能更改,因此通过名称指定它们通常是最简单的事情。您可以从实体描述中获取一组属性,但是如果您还不知道它的名称,您将如何知道要使用哪个属性呢?而且,如果您知道属性的名称,那么检索属性描述只是为了获取它的名称就没有多大意义。 ;-)

    有时在应用程序运行之前不确定实体和属性会很有帮助,例如,当您想让用户指定搜索参数时。但是,在您给出的示例中显然不是这种情况,因为您已经给出了谓词的格式。

    【讨论】:

    • 感谢您的回答。我认为,这实际上是有道理的 - 至少对我而言 ;-) 将其视为将运行时错误转换为设计/编译时错误。
    • 我可以理解这是否真的能让你更早地发现错误,但我不明白它是如何做到的。使用 [[Person class] description] 而不是 @"Person" 并不会减少名称“Person”与相应实体名称不匹配的可能性,并且编译器在任何一种情况下都不会捕获该错误。
    • 谢谢,我明白你的意思。我需要考虑清楚这一点。但是根据我在 c# 中的经验,我讨厌在字符串中编写属性名 ;-) 在重构过程中,这些事情总是会搞砸的。
    猜你喜欢
    • 2011-10-21
    • 1970-01-01
    • 2017-07-28
    • 2013-04-14
    • 2012-03-26
    • 1970-01-01
    • 1970-01-01
    • 2017-01-19
    • 1970-01-01
    相关资源
    最近更新 更多