35

I have strange new feature in xcode 7, when I generate new NSManagedObject subclass then xcode create two classes: entity and their CoreDataProperties category, which contain full implementation. In picture below an example what I mean.

enter image description here

I cannot find any documented info about this, who can explain why it works so

Pieter Kuijpers
  • 7,247
  • 5
  • 28
  • 36
Yevgeniy Logachev
  • 661
  • 1
  • 5
  • 11

3 Answers3

46

I just noticed this and also could not find any documentation about it but I've experimented with this new feature and it works like this. When you first generate NSManagedObject subclass from your Core Data model then Xcode will generate 4 files:

DBUser.h

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

NS_ASSUME_NONNULL_BEGIN

@interface DBUser : NSManagedObject

// Insert code here to declare functionality of your managed object subclass

@end

NS_ASSUME_NONNULL_END

#import "DBUser+CoreDataProperties.h"

DBUser.m

#import "DBUser.h"

@implementation DBUser

// Insert code here to add functionality to your managed object subclass

@end

DBUser+CoreDataProperties.h

#import "DBUser.h"

NS_ASSUME_NONNULL_BEGIN

@interface DBUser (CoreDataProperties)

@property (nullable, nonatomic, retain) NSNumber *id;
@property (nullable, nonatomic, retain) NSString *name;

@end

NS_ASSUME_NONNULL_END

DBUser+CoreDataProperties.m

#import "DBUser+CoreDataProperties.h"

@implementation DBUser (CoreDataProperties)

@dynamic id;
@dynamic name;

@end

So as you can see now all properties are in a separate file with category (CoreDataProperties). Later if you generate NSManagedObject subclass for the same model Xcode 7 will regenarete only 2 files with category (DBUser+CoreDataProperties.h and DBUser+CoreDataProperties.m) to update all properties from your model but it will not make any changes to 2 other files (DBUser.h and DBUser.m) so you can use these 2 files to add there some custom methods or properties etc.

In previous version Xcode generated always only 2 files (DBUser.h and DBUser.m) and it put properties there so you could not easily modify these files because your custom implementation was deleted everytime you regenerated your subclasses. Therefore it was a common practice to manually create a category and put your methods in your category which was oposite to what we can see in Xcode 7. That however had many disadvantages because we had to use a category for implementation of our methods which does not allow to do certain things and now we can easily modify the main interface and implementation files which allows us to do anything with it. Hurray!

Leszek Szary
  • 9,763
  • 4
  • 55
  • 62
  • How does Core Data generates categories with dynamic properties but in the same time, we can not add properties in our categories (at least not without associated objects)? – Dan Bodnar Nov 23 '15 at 16:26
  • 1
    I guess that core data properties are handled by the parent class (that is NSManagedObject) in very different way than normal properties as they must be read from and saved to a local database while normal properties just operate on some ivar's in memory. Possibly NSManagedObjects could generate setters and getters for its subclasses properties in runtime or something similar as this is possible in such a dynamic language as Objective-C (e.g. http://sam.dods.co/blog/2014/01/04/dynamic-accessors-for-category-properties/ gives some possible ideas how this kind of stuff could be implemented). – Leszek Szary Nov 24 '15 at 16:14
  • so are you saying that the reason we can have property declarations in this generated subclass is that the properties are "@dynamic"? – dave adelson Dec 19 '15 at 06:24
  • I'm saying that implementation of getters and setters for these properties must be dynamically provided at runtime by NSManagedObject class. – Leszek Szary Jan 02 '16 at 07:03
2

Previously the generated code went into a EntityName.h and EntityName.m that you had to "extend" with an interface such as EntityName+Create.h and EntityName+Create.m.

This was hard to understand for beginners who often modified the EntityName.m class and lost their code.

Now it is in the right way: the code generator will not erase the existing code.

The other answers are very good at explaining the new system.

But nobody talks about the new compatibility issue if you have entities based on the old system.

My solution: I still put my own code in EntityName+Create.m, but in EntityName+Create.h I refer to EntityName+CoreDataProperties.h instead of just EntityName.h (I emptied the previously generated code in EntityName.h and EntityName.m). This solution avoided me to move my code from EntityName+Create.m and to change all references to EntityName+Create.h.

I hope this helped you.

0

For Swift and Xcode 7 it is the same as the answer from Leszek S but only 2 files are created initially:

  • DBUser.swift
  • DBUser+CoreDataProperties.swift

Later, if you make changes to the CoreData model and regenerate the NSManagedObject subclass only the DBUser+CoreDataProperties.swift gets updated. DBUser.swift is left untouched.

So put all your code in DBUser.Swift.

Murray Sagal
  • 8,454
  • 4
  • 47
  • 48