【问题标题】:How do I get Core Data to use my own NSManagedObjectID URI scheme?如何让 Core Data 使用我自己的 NSManagedObjectID URI 方案?
【发布时间】:2010-08-30 15:49:25
【问题描述】:

我正在编写一个连接到数据库以获取数据的应用程序。由于获取成本高昂且数据通常不会发生变化,因此我使用 CoreData 来缓存结果,以便进行快速的本地查询。

从数据库中,对于每种类型,都有一个保证唯一的字符串属性。实际上,数据库有一个 URI 方案,它是每个项目的唯一地址。

URL 方案是非常基本的:

ngaobject:////

我也希望能够在 CoreData 中使用它。我已经创建了一个从 CoreData 存储中获取单个项目的方法:

-(NSFetchRequest*)fetchRequestForType:(NSString*)typeName identifier:(NSString*)identifier
{
    NSFetchRequest * fetchRequest = [self fetchRequestForType:typeName];

    [fetchRequest setFetchLimit:1];

    NSString * identifierProperty = [self identifierPropertyNameForObjectType:typeName];
    NSPredicate * predicate = [NSPredicate predicateWithFormat:@"%K == %@", identifierProperty, identifier];
    [fetchRequest setPredicate:predicate];

    return fetchRequest;
}

-(NGAObject*)objectWithType:(NSString*)typeName
identifier:(NSString*)identifier
    {
        // First try to retrieve it from the cache

    NSAssert1( (identifier != nil), @"Request to create nil-name object of type %@", typeName );

    NSFetchRequest * fetchRequest = [self fetchRequestForType:typeName identifier:identifier];

    if ( !fetchRequest )
        return nil;

    NSError * error = nil;
    NSArray * fetchResults = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];

    if ( !fetchResults )
    {
        NSLog(@"%@", error);
        [NSApp presentError:error];
        return nil;
    }

    if ( [fetchResults count] )
        return [fetchResults objectAtIndex:0];

    return nil;
}

当我从服务器检索一个项目时,我想首先在缓存中获取对它的引用,如果它在那里,更新它。如果不是,请创建一个新的。

由于我从服务器取回了数千个对象,因此对我知道其唯一 ID 的单个对象执行提取会使我的机器陷入爬网状态。

相反,我正在做的是预加载一个类型的所有对象,然后创建一个标识符字典 -> 对象,然后通过在字典中运行它来处理该类型的数千个对象。这很好用,但很尴尬。

难道我不能编写一个方法来获取类型/标识符组合并从 CoreData 获取单个对象,而不必执行冗长的获取请求吗?

如果我可以让 CoreData 使用我自己的 URI 规范,似乎有一个解决方案。然后我可以在持久存储协调器上调用 -(NSManagedObjectID*)managedObjectIDForURIRepresentation:(NSURL*)url

那么,问题是,我怎样才能让 CoreData 使用我的 URI 方案?如何让 CoreData 使用我自己的唯一标识符?

【问题讨论】:

    标签: cocoa cocoa-touch core-data


    【解决方案1】:

    您不能让 Core Data 使用自定义 URI 方案。 URI 方案被硬编码到核心数据中,以便可以对 URI 进行解码,以在特定硬件上的特定应用程序中的特定商店中定位特定数据。如果 URI 是可定制的,那么该系统就会崩溃。

    单独获取对象会杀死你。相反,您需要批量获取其 customID 与服务器提供的对象匹配的所有对象。最简单的方法是使用IN 谓词运算符:

    NSArray *customIDs=//... array of customIDs provided by server
    NSPredicate *p;
    p=[NSPredicate predicateWithFormat: @"customIdAtrribute IN %@", customIDs];
    

    这将返回您可以忽略的所有现有对象。

    你也可以

    1. 通过将提取的propertiesToFetch 设置为customID 属性,仅对customID 属性进行提取。
    2. 将获取结果类型设置为字典。
    3. 使用上述谓词。
    4. 您将获得一个键字典的数组,该字典以 customID 作为每个值返回。
    5. 将字典转换为值数组,例如cachedIDs
    6. 将上面的customIDs 转换为可变数组。
    7. 使用谓词@"NOT (SELF IN %@)", cachedIDs" 过滤customIDs 数组
    8. 过滤后的customIDs 数组现在将只包含未缓存在Core Data 中的customID 值。
    9. 您只能为新 ID 创建托管对象。

    (如果您不熟悉过滤谓词,这就是您如何使用它。)

    NSMutableArray *f=[NSMutableArray arrayWithObjects:@"1",@"2",@"3",@"4",@"5",@"6",nil];
    NSArray *g=[NSArray arrayWithObjects:@"5",@"6",nil];
    [f filterUsingPredicate:[NSPredicate predicateWithFormat:@"NOT (SELF IN %@)",g]];
    NSLog(@"f=%@",f);
    

    ...输出:

    f=(
        1,
        2,
        3,
        4
    )
    

    【讨论】:

      【解决方案2】:

      您用于唯一 ID 查找的所有字段是否在 CoreData 设计器中都标记为“已索引”?如果已经这样做了,那么 CoreData 提取应该不会很长......

      【讨论】:

      • 不,不是。这是一个很好的建议,我会试一试。只是为了这个问题,有没有办法完成我所布置的?
      • 不确定,这里的另一个问题似乎不建议。一般来说,如果你发现自己试图破解 CoreData 工作原理的内部问题,那么你可能做错了什么。在这种情况下,我很确定最好的解决方案就是使用表索引,这将是建议的 CoreData 方法(实际上这适用于任何 RDBMS)
      猜你喜欢
      • 2011-01-27
      • 2021-04-30
      • 1970-01-01
      • 1970-01-01
      • 2020-07-25
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      • 2019-01-16
      相关资源
      最近更新 更多