Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Don't do this; what you're doing is porting a pattern from one context to another where it doesn't really make sense.</p> <p>For one thing, you shouldn't be modeling IDs at all in Core Data; the framework does that for you with NSManagedObjectID already. Thus a <code>-clientWithID:</code> method on a CoreDataDAL class is redundant. (Note that I've also changed the name of your hypothetical method to follow proper Cocoa naming conventions.) Instead, you can just use <code>-[NSManagedObjectContext objectWithID:]</code> or <code>-[NSManagedObjectContext existingObjectWithID:error:]</code> to get an object based on its NSManagedObjectID.</p> <p>Similarly, relationship management is handled for you. You don't need to have a method in your DAL that can (say) fetch all of the Address instances that apply for a given Client by evaluating some query. You can just traverse your Client's to-many <code>addresses</code> relationship to get at them, and manipulate the same relationship directly (rather than setting foreign keys etc.).</p> <p>Finally, if you really do want to have methods to perform specialized queries, you can either specify the query via a fetched property on the appropriate entity for its results, or you can add that method <em>directly to the appropriate class</em>. Class methods in Objective-C aren't like static methods in C++, Java or C# - they can be overridden just as instance methods can, and are much more appropriate for this kind of use.</p> <p>For example, say your Client entity has a <code>syncID</code> property representing the ID of the object that it represents in some web service. (Note that this is specifically for relating a local object to a remote object, not the "primary key" of the local object.) You'd probably have class methods on the MyClient class associated with your Client entity like this:</p> <pre><code>@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] &gt; 0) { result = [results objectAtIndex:0]; } else { if (error != NULL) { *error = [NSError errorWithDomain:MyAppErrorDomain code:MyAppNoClientFoundError userInfo:nil]; } } return result; } @end </code></pre> <p>This is similar to what you wrote in your DAL class, but instead of consolidating all of the fetches in one place, it puts the logic for fetches appropriate to a particular managed object class on that class, which is really where it belongs. Thanks to the fact Objective-C has true class methods, you can actually put methods like <code>+entityInManagedObjectContext:</code> and <code>+entityClassName</code> on a common base class and then override only the latter as appropriate in subclasses (or even have it generate an appropriate entity name from the class name).</p> <p>To sum up:</p> <ul> <li>Don't recreate what Core Data already implements for you in terms of things like object IDs, relationship management, and so on.</li> <li>Leverage polymorphism at both the instance <em>and</em> the class level to keep your code clean, rather than use "utility" classes like "data access layers."</li> </ul>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload