如何将所有获取请求放入Core Data DAL?

Sle*_*lee 1 iphone core-data objective-c ipad

来自.net背景的Objective-C和Core Data的全新内容我真的想把我的所有获取请求都放到我可以调用的某种类中,最好是静态地获取我的对象,例如:

ObjectType*myObject = [CoreDataDAL GetObject:ID];

任何人都有实现这个的模式?

我现在正在通过一个攻击我的方式,但它可能不太正确,我会在发布时发布代码.

EIDT:这是我现在的代码 - 似乎工作得很好 - 如果我走错路,请把它撕掉 - 这是基本的DAL:

#import "CoreDataDAL.h"
#import "CoreDataAppDelegate.h"

@implementation CoreDataDAL

@synthesize managedObjectContext;

-(id)init {
    if (self=[super init]) {
        CoreDataAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
        self.managedObjectContext = appDelegate.managedObjectContext;
    }
    return self;
}

-(Client *) GetClient:(NSString *) ClientID{
    /* Client Fetch Request */
    NSFetchRequest *request = [[NSFetchRequest alloc]init];
    NSEntityDescription *entityType = [NSEntityDescription entityForName:@"Client" inManagedObjectContext:managedObjectContext];
    [request setEntity:entityType];
    NSPredicate *predicate =[NSPredicate predicateWithFormat:@"ClientID==%@",ClientID];
    [request setPredicate:predicate];

    NSError *error;
    NSArray *entities = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];

    return [entities objectAtIndex:0];
}

@end
Run Code Online (Sandbox Code Playgroud)

以下是我在视图控制器中的使用方法:

CoreDataDAL *dal = [[CoreDataDAL alloc]init];
Client *client = [dal GetClient:clientID];
[dal release];
Run Code Online (Sandbox Code Playgroud)

似乎直截了当,想法?

Chr*_*son 14

不要这样做; 你正在做的是将一个模式从一个上下文移植到另一个上下文中,它实际上没有意义.

首先,您不应该在Core Data中对ID进行建模; 框架为您完成了NSManagedObjectID.因此-clientWithID:,CoreDataDAL类上的方法是多余的.(请注意,我还更改了您的假设方法的名称,以遵循正确的Cocoa命名约定.)相反,您可以使用-[NSManagedObjectContext objectWithID:]-[NSManagedObjectContext existingObjectWithID:error:]根据其NSManagedObjectID获取对象.

同样,为您处理关系管理.您不需要在DAL中有一个方法可以(比方说)通过评估某个查询来获取应用于给定客户端的所有Address实例.您可以遍历客户端的多对多addresses关系以获取它们,并直接操纵相同的关系(而不是设置外键等).

最后,如果您确实希望有方法来执行专门的查询,您可以通过相应实体上的fetched属性为其结果指定查询,也可以将该方法直接添加到相应的类中.Objective-C中的类方法与C++,Java或C#中的静态方法不同 - 它们可以像实例方法一样被覆盖,并且更适合这种使用.

例如,假设您的客户端实体具有一个syncID属性,该属性表示它在某些Web服务中表示的对象的ID.(请注意,这是专门用于将本地对象与远程对象相关联,而不是本地对象的"主键".)您可能在与客户端实体关联的MyClient类上有类方法,如下所示:

@implementation MyClient

+ (NSString *)entityClassName
{
    return @"Client";
}

+ (NSEntityDescription *)entityInManagedObjectContext:(NSManagedObjectContext *)context
{
    return [NSEntityDescription entityForName:[self entityClassName] inManagedObjectContext:context];
}

+ (MyClient *)clientWithSyncID:(NSString *)syncID
        inManagedObjectContext:(NSManagedObjectContext *)context
                         error:(NSError **)error
{
    MyClient *result = nil;

    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:[self entityInManagedObjectContext:context]];
    [request setPredicate:[NSPredicate predicateWithFormat:@"syncID == %@", syncID]];
    [request setFetchLimit:1];

    NSArray *results = [context executeFetchRequest:request error:error];
    if ([results count] > 0) {
        result = [results objectAtIndex:0];
    } else {
        if (error != NULL) {
            *error = [NSError errorWithDomain:MyAppErrorDomain
                                         code:MyAppNoClientFoundError
                                     userInfo:nil];
        }
    }

    return result;
}

@end
Run Code Online (Sandbox Code Playgroud)

这与您在DAL类中编写的内容类似,但它不是在一个位置合并所有提取,而是将提取的逻辑放在该类的特定托管对象类上,这实际上就是它所属的位置.由于这样的事实:Objective-C的具有真实类方法,实际上你可以把类似的方法+entityInManagedObjectContext:,并+entityClassName在一个共同的基类,然后只覆盖后者为适当的子类(甚至有它生成的类名合适的实体名称).

总结一下:

  • 不要在对象ID,关系管理等方面重新创建Core Data已经为您实现的内容.
  • 利用实例类级别的多态来保持代码清洁,而不是使用"数据访问层"之类的"实用程序"类.