Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the functional differences between Coredata's CodeGen 'manual/none + create NSManagedObject subclass' vs. 'category/extension'

I've read Subclassing NSManagedObject with swift 3 and Xcode 8 beta and read this great tutorial. Still have questions on some points.

The similarities are:

  1. I can customize both classes however I like.
  2. I can add new attributes or remove or rename attributes. ie for category/extension it will get updated upon a new build (in the derived data), and in case of manual/none it will leave the class file intact and update the extension in the file navigation ie I won't end up with a duplicate file. This is all handled by Xcode because they are marked with a preprocessor @NSManaged
  3. Dumping something like @NSManaged public var name: String? straight into an existing NSManagedObject subclass is not allowed. I tried to do entity.name = "John" but I got the following error: reason: '-[SomeEntity setName:]: unrecognized selector sent to instance 0x60400009b120'. I believe that's reasonable. I think without using the Core Data Model Editor the setter/getter accessor methods are not created.

The differences are:

  1. For Category/Extension you just need to create the class yourself and add any extra functions/properties you need.
  2. For Category/Extension the attributes are created in derived data which is enough. Because you never need to see that file. Its existence is enough to get things working.

    
And specifically in the context of making changes to your NSManaged properties:

  3. Changing property type, e.g. NSDate to Date is allowed only for Manual/None . Example here

  4. Changing optionality of a type, e.g. String? to String is allowed only for Manual/None. Example here
  5. Changing a property access level, e.g. from public to private is allowed only for Manual/None. Example here

  6. Having that said there is significant difference if I choose Manual/None codegen and but don't select 'create NSManagedObject subclass'. In that case I have start writing all the code myself (subclass from NSManagedObject and write NSManaged for every property)...or if I don't write all that code myself then I can still access/set fields using KVC which is awkward!

In a nutshell I'm just trying to figure out the full extent of capabilities that I can get from using Manual/None.

Question: Aside from the 9 notes which I need to know if I have validated correctly, an important question would be: how does me changing NSDate to Date or optional to non-optional not break the mappings between my NSManagedObject class and my object graph all while changing an NSDate property to String does break!! Does this have something to do with things that have guaranteed casting between Swift and Objective-C ie things that can be casted through as — without ? or !?

like image 383
mfaani Avatar asked Dec 21 '18 21:12

mfaani


People also ask

What is codegen in Core Data?

The Codegen menu is where you specify the code generation for the entity. There are three code generation options. Choosing Manual/None tells Xcode not to generate code for the entity. You must create the class for the entity by creating a new file or by choosing Editor > Create NSManagedObject Subclass.

How do I create a subclass in NSManagedObject?

From the Xcode menu bar, choose Editor > Create NSManagedObject Subclass. Select your data model, then the appropriate entity, and choose where to save the files. Xcode places both a class and a properties file into your project.

What is NSManaged?

NSmanaged is subclass of NSObject. @NSManaged means extra code will be given to these props at runtime. It tracks the changes made to those properties.

How do I use Core Data?

Use Core Data to save your application's permanent data for offline use, to cache temporary data, and to add undo functionality to your app on a single device. To sync data across multiple devices in a single iCloud account, Core Data automatically mirrors your schema to a CloudKit container.


1 Answers

To address each of your notes and considering the cases where codegen is set to Manual/None and Category/Extension:

  1. Yes, in either case you can customise the classes however you like (within limits - for example, the class must be a subclass - directly or indirectly - of NSManagedObject).
  2. Correct. You can add, amend or delete attributes in the model editor. In the Category/Extension case, the relevant changes will be made automatically. In the Manual/None case, you can either manually update the Extension (or the class file) or you can redo the "create NSManagedObject subclass" which will update the Extension with the amended attribute details. If you do not do this, Xcode will not recognise the new attribute details and will not provide code completion for them (nor will it successfully compile if you try to override code completion). But unlike what you think this has nothing to do with the properties being marked as @NSManaged.
  3. Correct. Adding an @NSManaged property to the class definition (or Extension) is enough to tell Xcode that the property exists (so you can reference them in code) but does not create the corresponding getter/setter. So your code will crash.
  4. Yes, for Category/Extension just create and tailor the class file as you require.
  5. Yes, for Category/Extension the properties are declared in the automatically created Extension file in Derived Data.
  6. Changing the property definition in any way - from Date to NSDate, or marking it private, or whatever - can only be done in the Manual/None case because the Extension file in Derived Data is overwritten with each new build so any changes are lost.
  7. Ditto
  8. Ditto
  9. Correct. You could write your app without ever creating separate NSManagedObject subclasses (automatically or manually), if you use KVC to access the properties.

As to your final point: you cannot arbitrarily change the type of the property definition: the type specified in the model editor must correspond to the type specified in the property definition. You can switch between optional and non-optional versions of the same type, and you can switch between Date and NSDate etc, but switching from Date to String will not work. I suspect you are correct that this is due to the bridging between Swift value type and the corresponding Objective-C reference type using as. See here.

like image 189
pbasdf Avatar answered Nov 08 '22 07:11

pbasdf