I have the following problem:
As our app is going to be shown to potential customers it has to run offline in first version (due to dependencies to a backend that is not finished right now) and therefore all the data shown in the app will be retrieved by CoreData from a sqlite db. As we want to avoid later refactoring we decided to put the CoreData entities behind protocols. A service will take care of all the data retrieval and hide the entities with the corresponding protocols.
In a later version of the app the UI developers will just switch the service to the backend one's and do not have to alter the rest of their code due to sticking to the protocols. For UI developer it does not make a difference if the entities will be NSManagedObjects or just NSObjects.
And now comes the problem. We have declared the protocols (set- and get-Methods) for all the entities in our app and generated CoreData entities that fit to those protocols. CoreData is using @dynamic for all the set/get-Methods (that will we be generated during runtime from the CoreData framework).
All the NSManagedObjects should now implement their corresponding protocols, but the compiler is giving out warnings (because of @dynamic) that the CoreData-Object is not implementing the protocol.
I just want to give you ONE entity and the corresponding protocol to explain my problem in detail:
TaskCD.h
@interface TaskCD : NSManagedObject<Task> {
@private
}
@property (nonatomic, retain) NSString * category;
@property (nonatomic, retain) NSNumber * frequency;
@property (nonatomic, retain) NSDate * validityEnd;
@property (nonatomic, retain) NSDate * validityStart;
@property (nonatomic, retain) NSNumber * periodicity;
@property (nonatomic, retain) NSString * descr;
@property (nonatomic, retain) NSNumber * selected;
@property (nonatomic, retain) NSSet* measurements;
@end
TaskCD.m
#import "TaskCD.h"
#import "MeasurementCD.h"
@implementation TaskCD
@dynamic category;
@dynamic frequency;
@dynamic validityEnd;
@dynamic validityStart;
@dynamic periodicity;
@dynamic descr;
@dynamic selected;
@dynamic measurements;
.... CoreData One-To-Many-stuff ....
@end
Task.h
@protocol Task <NSObject>
- (NSString*) getCategory;
- (void) setCategory:(NSString*) category;
- (NSNumber*) getFrequency;
- (void) setFrequency:(NSNumber*) frequency;
- (void) setValidityEnd:(NSDate *) date;
- (NSDate *) getValidityEnd;
- (void) setValidityStart:(NSDate *) date;
- (NSDate *) getValidityStart;
- (void) setPeriodicity:(NSNumber *) number;
- (NSNumber *) getPeriodicity;
- (void) setDescr:(NSString *) descr;
- 开发者_高级运维(NSString *) getDescr;
- (void) setSelected:(NSNumber *) selected;
- (NSNumber *) getSelected;
- (void) setMeasurements:(NSSet*) measurements;
- (NSSet *) getMeasurements;
@end
I am not that experienced with ObjC and I am coming from Java Development. Maybe it is a design failure and not an ObjC issue. What we want to definitely stick with, is that in the productive version with the real backend the UI developer should NOT work with NSManageObject classes to keep away the CoreData stuff. He just sees one facade giving him an API to interact with the layers behind (First CoreData. Later REST backend). The UI developer should only see plain VOs or stick to protocols (interfaces).
I just want to know how to avoid those warnings. All proposals are welcome. ;)
Thanks in advance guys!!
One thing I can suggest off the bat: the accessors defined in Task.h should match the names of the @property declarations in the TaskCD interface. Instead of:
- (NSString*) getCategory;
you should declare it as:
// this is the more common Obj-C naming convention
- (NSString*) category;
Alternately, specify the name of the "get" accessor in the @property declaration (in TaskCD.h):
//meh... not so nice
@property (nonatomic, retain, getter=getCategory) NSString * category;
Also IMHO, with Core Data you're much better off using the dynamically generated accessors, rather than implementing your own.
First, I want to say that I agree with octy in that the best solution would probably be just to change your protocol to use more standard Objective-C accessor names.
However, I also wanted to throw out the option that you could create a category for each of your generated CoreData objects that essentially maps their accessor methods to the accessor names you want:
@interface TaskCD (Accessors) <Task>
...
@implementation TaskCD (Accessors)
- (NSString *) getCategory {
return [self category];
}
...
This way, you can keep the generated files (and regenerate them however often you like) and still use your own accessor method names.
That being said, I still think it would be better to just stick with the Objective-C default accessor names.
there is another approach you could follow: keep core data even in your later REST version and simply update your local core data storage with the live data respectively use the NSManagedObjects. using core data in UI stuff is actually a good idea, because the you get a lot of benefits (e.g. feeding tableviews which successively fetch rows from core data when scrolling)
精彩评论