I am trying to wrap my head around CoreData, and came across MagicalRecord.
I've been messing around with objc/ios development most recently. I am used to having a Service Layer that handles the fetching/creating of a model. I am trying to figure out what is the best approach in ios.
Do I handle my Data access layer within the model where it fetches a user or should this logic be done from the controller?
// User.h
+ (User *)initWithUserId:(NSString *)userId; // AFNetworking fetches user and saves to core data
// Account.h
+ (Account *)initWithUsername:(NSString *)username andPassword:(NSString *)password
// Account.m
+ (Account *)initWithUsername:(NSString *)username andPassword:(NSString *)password
{
__block Account *account;
[[HTTPSessionManager sharedClient] POST:@"/authenticate" parameters:@{@"email":username,@"pw":password} success:^(NSURLSessionDataTask *task, id responseObject) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)task.response;
NSString *authToken = [[httpResponse allHeaderFields] objectForKey:@"Auth-Token"];
account.password = password;
account.token = authToken;
account.user = [User initWithUserId:responseObject['_id']];
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"Error: %@", error);
}];
return account;
}
// LoginViewController.m
- (void)signIn
{
NSString *username = self.usernameTextField.text;
NSString *password = self.passwordTextField.text;
Account *account = [Account initWithUsername:username andPassword:password];
if (account objectID) {
// sign in successful
}
}
First, you're not using the proper Objective C conventions. init methods are never class methods. I suggest you read some of the Apple Documentation regarding object initializers. Second, I highly recommend against firing a network request from an initialization method.
And third, the actual question was whether Core Data objects are good for putting this type of network/data model translation code. In general, data objects should have methods that perform actions against those objects. Whether they launch a network request, process data or anything else should be a secondary concern, and definitely not something you expose to the consumers of those data objects.
In the case where network requests are fired, or more generally, asynchronous scenarios, you should design your interface such that a completion signal is called once the operation is complete. In ObjC, you can use a completion block, or a delegate for that.