Oleksandr Matrosov
Oleksandr Matrosov

Reputation: 27133

Core data. NSPredicate issue using constant literals as names of properties

I have NSManagedObject with properties. Suppose that one property it is:

@property (retain, nonatomic) NSString *city;

For fetching data form core data I always use NSPredicate. The predicate looks like below:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", @"city", @"San Francisco"];

But the problem here that the project use key "city" as undefined key in meaning like a constant. So lets suppose that I use key "city" in my app 1000 times, so then I need to replace all this keys with new one if property of NSManagedObject was changed, e.g. to cityName. In this case I need to use predicate:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K == %@", @"cityName", @"San Francisco"];

It is not comfortable. So right now I am using global extern NSString key kCity = @"city"; but in case if the data model changed as well there is a problem, because if property will be changed I will have crash only when run app and console will say me:

'key path city not found in entity <NSSQLEntity...

Which workaround can be here? I thought using something like

NSString * const kCity = myEntity.city.propertyString;

So if property was changed then parser will tell me that project has an error and I can't run app. So after I change property for constant only then I will be able to run app

How can get name of property in NSString. Of course it is just suggestion and maybe someone have another variant.

Thanks

Upvotes: 2

Views: 515

Answers (2)

e1985
e1985

Reputation: 6279

I use this macro-based solution to avoid string literals when I want the name of a key.

It allows you to write key names in this fashion:

[NSPredicate predicateWithFormat:@"%K = %@", Key(YourManagedObjectSubclass, propertyName), @"aValue"];

The compiler will check if YourManagedObjectSubclass has a property of the given name.

But of course, keep in mind that if you change an attribute name in your data model you still need to change it in your NSManagedObject subclass.

Upvotes: 0

Matthias Bauch
Matthias Bauch

Reputation: 90117

You could use mogenerator, one thing it does is to create a struct for attribute and relationship keys that you can use.

// .h
extern const struct MBListAttributes {
    __unsafe_unretained NSString *title;
} MBListAttributes;

// .m
const struct MBListAttributes MBListAttributes = {
    .title = @"title",
};

You can then use MBListAttributes.title to get the correct key.

Upvotes: 2

Related Questions