What Are the Functional Differences Between Coredata's Codegen 'Manual/None + Create Nsmanagedobject Subclass' VS. 'Category/Extension'

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

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.

Xcode 8 generates broken NSManagedObject subclasses for iOS 10

I finally got mine to work. Here is what I did. (Flights is one of my entities)

I setup the xcdatamodeld as follows

Sample Image

And then the entity as

Sample Image

Then I used Editor -> Create NSManagedObject Subclass

This creates two files for my flights entity

Flights+CoreDataProperties.swift

Flights+CoreDataClass.swift

I renamed Flights+CoreDataClass.swift to Flights.swift

Flights.swift is just

import Foundation
import CoreData

@objc(Flights)
public class Flights: NSManagedObject {

}

Flights+CoreDataProperties.swift is

import Foundation
import CoreData


extension Flights {

@nonobjc public class func fetchRequest() -> NSFetchRequest<Flights> {
return NSFetchRequest<Flights>(entityName: "Flights");
}

@NSManaged public var ...
}

This appears to work for me.I could not get Codegen to work in any other way, even though I tried many of the suggestions that were out there.

Also this had me scratching my head for a while and I add it as an assist. Don't forget with the new Generics version of the FetchRequest you can do this

let fetchRequest: NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Flights")

Subclassing NSManagedObject with swift 3 and Xcode 8 beta

It's probably a (beta) clash with the new automatic subclass generation, which can be controlled in the entity inspector of the data model file.

From the documentation (What's New In Core Data)

Xcode automatic subclass generation


Xcode now supports automatic generation of NSManagedObject subclasses
in the modeling tool. In the entity inspector:

  • Manual/None is the default, and previous behavior; in this case you
    should implement your own subclass or use NSManagedObject.
  • Category/Extension generates a class extension in a file named like
    ClassName+CoreDataGeneratedProperties. You need to declare/implement
    the main class (if in Obj-C, via a header the extension can import
    named ClassName.h). -
  • Class Definition generates subclass files named
    like ClassName+CoreDataClass as well as the files generated for
    Category/Extension.

The generated files are placed in DerivedData and
rebuilt on the first build after the model is saved. They are also
indexed by Xcode, so command-clicking on references and fast-opening
by filename works.

NSManagedObject subclass property in category

In previous Xcode releases, only a class was created for each
Core Data entity, e.g. the class "BibleAudio" in BibleAudio.h/.m. These files were overwritten each time you
re-created the managed object subclasses. Therefore, to add
your own functionality to the Core Data class, you had to define
a category (in separate files) on the class.

The great disadvantage
was that you can add methods in class categories, but not
instance variables. So you could not add a simple property
(backed up by an instance variable). One possible workaround was to
define a transient property in the entity, but this had also
disadvantages.

Now Xcode creates a class "BibleAudio" (in BibleAudio.h/.m) which is essentially empty,
and a category "BibleAudio (CoreDataProperties)" in
BibleAudio + CoreDataProperties.h/.m
The category files contain all the Core Data properties, and are
overwritten when you re-create the managed object subclasses.

The class files BibleAudio.h/.m are created only once and never overwritten. You can add functionality there: methods as before, but also custom properties and instance variables. Because it is a class
and not a category, the old restrictions don't apply anymore.

Xcode 8 automatic NSManagedObject sublass codegen vs transient properties

I do not think this is possible without generating the NSManagedObject subclasses.

This is likely what the "Category/Extension" codegen option helps to address. This codegen option is useful for creating properties (attributes) that you do want Core Data to manage.

Why exactly would one subclass NSManagedObject?


I still don't really get what subclassing NSManagedObject is for - what role does it play?

Convenience for the developer - in terms of CodeSense, shorter syntax, and some compile-time checks that help thwart misspellings of keys.

so what can I do with NSManagedObject? What are the restrictions, must-follow guidelines, and what aren't restrictions?

The UI built into Xcode will make the NSManagedObject subclasses for you - you really don't need to do it by hand - but, basically, they are just NSManagedObjects with some properties tacked on. Instead of using @synthesize or such, you use @dynamic and Apple takes care of the rest for you - hooking up those properties to getters/setters which mimic what you would normally do with a "bare" NSManagedObject.

I'm trying to make a little box drawing program to learn Core Data, and I'm thinking of adding "draw" methods to a subclass of NSManagedObject so that a view can just tell them to draw for itself - is this permitted?

You could.... but I wouldn't. This sounds like bad design - try to keep your Model and Controllers separate.

Model objects shouldn't contain business logic / drawing code. Use the model simply as the "state" of your application. Make something else responsible for the drawing. Plus, while I can't say this with absolute authority, I believe there is some overhead if you're dealing with updating / retrieving info from an NSManagedObject.

(Basically, it's like dealing with an NSDictionary... sorta. It's less efficient to grab items out of a dictionary than it is to access an ivar.)

For an app that does things like drawing - you'll probably want to avoid that overhead by making a structure for your in-memory things, and possibly a second, similar structure for persistence/serialization (like to CoreData).

So, my question in one sentence would be, what's the "real" difference
between subclassing NSManagedObject and any other class - what does
Core Data do with it?

I would say - don't subclass NSManagedObject by hand at all - use what Xcode gives you. If you want more (other than maybe a custom constructor) then you're probably barking up the wrong tree.

EDIT:

I think there might have been some confusion about what I meant when I said "don't subclass NSManagedObject by hand at all"

To elaborate, and incorporate one of the responses:

Start with the data model designer in Xcode, create your models, and use the following menu option:

Sample Image

Then, you could modify the generated class to include custom:

  • Constructors
  • Data Conversion Methods
  • Validation
  • Formatting
  • Sort Descriptors
  • Filters

If your use case doesn't fit in that list, you should really seriously think about putting it somewhere else (as in your example with the "Draw" method).

All of those things mentioned above could be tacked on to an NSManagedObject subclass which was created for us by Xcode (we didn't create "by hand") - and they all revolve around dealing with the data directly (formats / conversions / etc) and/or around pulling the data out of Core Data (filters / sorting).

They don't add iVars, they don't perform any complicated operations outside of the scope of data storage and retrieval.



Related Topics



Leave a reply



Submit