Fails at setting codegen into CoreData - ios

when setting codegen on Entities(Tag, Note, Category) in Data Model on Category/Extension and module 'Current Product Module'
then I get 20 errors
errors open this hidden from project file:
My Core Data Model:
enter image description here
I reading a book "mastering core data with swift" by Cocoacasts

If you set the code generation to "category/extension", Xcode will not create a class for the entity, only a category or extension. If you use this type of generation, you must create a class. Xcode will only generate the extension, and if you don't create your own, then it's extending a nonexistent class. If you want to use this style of code generation, you need to create the class yourself.
If you set the code generation to "class definition", Xcode creates the class.

To get rid of the errors, you should set codegen on Entities(Tag, Note, Category) in Data Model on Manual/None

Related

Generating NSManagedObject Subclasses CoreData [duplicate]

Using Version 8.1 of Xcode.
Create an entity named "MapRegionObject" in .xcdatamodeld file.
Using auto code generator, click Editor on the navigation bar -> create NSManagedOject Subclass...
Got two files : MapRegionObject+CoreDataClass.swift and MapRegionObject+CoreDataProperties
Errors in two files showing in the screenshot:
MapRegionObject+CoreDataClass.swift
MapRegionObject+CoreDataProperties
Please help me fix this bugs, thank you so much!
In Xcode 8.1, before using the auto code generator, you must select the entity in your data model:
Then go to the Data Model Inspector tab:
Under "Codegen" select "Manual/Node"
After that you could create a NSManagedObject subclass without errors.
Alternatively, if you have already used 'Class Definition', you can go into your existing .xcdatamodeld file and set all current entities to 'Manual/None' under Codegen. Make sure to save your project (File -> Save), delete your existing Derived Data, clean the project, and then build. Resolved it for me without having to re-make my whole model.
I found this whole thing to be very confusing. You really do need to understand what's new in CoreData. Basically, the default is to automatically generate the class and the extensions for you in a place called "DerivedData" that's buried in ~/Library/Developer/Xcode/DerivedData where these classes and their extensions live, outside of your code source. Personally, not being able to open and look at them is weird to me, but something to get used it.
Basically, if you have an entity called "AppSettings" in your CoreData model, you can just use it without needing to generate the code yourself. If you want the code in your project, then set the Codegen property on the entity to Manual/None. Then do what you did before: Editor->Create NSManagedObject classes, etc. The files will wind up in your project.
The good news is that if you want to make custom extensions, just do that in your project. Xcode will blend the generated files, from their other place outside your project directory, with the files in your project directory.
1) clean the project (cmd + shift + K)
2) In the "data model inspector" for every created Entity set attributes for Class just as in the screenshot below
3) Generate code again (Editor -> create NSManagedObject Subclasses)
After that everything should work fine.
The problem is that you don't need to generate NSManagedObjectModel subclasses manually anymore.
ref: https://forums.developer.apple.com/thread/48988
Xcode automatically generates classes or class extensions for the
entities and properties in a Core Data data model. Automatic code
generation is enabled and disabled on an entity by entity basis, and
is enabled for all entities in new models using the Xcode 8 file
format. This feature is available for any data model that has been
upgraded to the Xcode 8 format. You specify whether Xcode generates
Swift or Objective-C code for a data model using the data model’s file
inspector. When automatic code generation is enabled for an entity,
Xcode creates either a class or class extension for the entity as
specified in the entity's inspector: the specified class name is used
and the sources are placed in the project’s Derived Data. For both
Swift and Objective-C, these classes are directly usable from the
project’s code. For Objective-C, an additional header file is created
for all generated entities in your model: The file name conforms to
the naming convention 'DataModelName+CoreDataModel.h'.
Close the project and follow the following instructions:
Reveal in finder your database .xcdatamodeld file.
on .xcdatamodeld file right click -> Show Package Contents, if(.xcdatamodel) is find again in the package again right click and 'Show Package Contents'. you should get 'contents' file.
Open 'contents' in text edit.
Command-F (codeGenerationType="class") and replace all matchings string with blank string.
Save and open Xcode project again.Everything should work well.
In Xcode 8.2.1 , Menu-Product-Clean,And every is ok, it's so verid.
Don't fight the with Xcode on this unless you really need to alter your generated properties, doing so will just leave you frustrated.
Think of the auto-generated class as any other class in your application. If you need to add functionality to your managed object class, simply change your class definition into an extension and extend your object.
change your class:
class MyManagedObject : NSManagedObject { /* implementation*/ }
to an extension:
extension MyManagedObject { /* implementation */ }
This isn't an answer. It's just explanation of what's going on with the selections
Make sure you see this moment for the Core Data Stanford course
Below is a transcript I wrote myself (It's not 100% accurate):
The default is class definition, if you choose this one. It will
generate that subclass and it will just work. You'll be able to access
your tweets as a class called Tweet. This sounds good. Btw if you do
this it will NOT show up in your file navigator.
The one we choose the most often is the category/extension what this
will do it will only generate an extension of the Tweet class. You
have to actually write the tweet class itself. The extension will take
care of making all the vars. Even when I switch to category/extension
again I don't get that extension showing up in the navigator. It's
kind of hidden from you.
And why do we like this one? Because a lot of times we want to add our
own code. Like in a Tweet, imagine you want to add a static method
that took data from Twitter and turned it into a tweet in the
database. Where would we put code? Well a great place to put that code
would be in the Tweet class...if there was such a thing...and the
extension is going to handle all the var business for you.
If you did choose manual/none for codegen. meaning don't do any
codegen, then you would be doing value/setValue(forKey:)...good luck
with that You're code is going to be a mess. [ie there is no
.propertyName = value ...you'd had to do setValue(value, forKey:
propertyName)].
Long story short, I'm not sure why but for some reason if you don't select the create NSManagedObject subclass then it seems to still work, but without showing what's happening under the hood. Very counter intuitive!
Then also watch this live demo of the Core Data Stanford course:
Now we know we want to access all this stuff not using
value/set(value:forKey:)...we want to have to subclasses of
Users/Tweets. And we want to have vars [ dot notation] for all these
relationships so we need that code to be generate. The way we do that
we just select the entity... and we go down here to CodeGen. This says
by default class definition. That means it's done it. It has generate
a class called Tweet. and It's going to work with var and all
relationships. That's not actually what we want. We want to select
this one [Category/Extension]. Where only create an extension to Tweet
and add the var stuff. That's because we want to write the class
Tweet and put our own code in there. It's very common to write our
own class. But you still want the var magic.

Invalid redeclaration on CoreData classes

I am working with CoreData, on an entity called "RoleName".
The problem is: I click on "Create NSManagedObject subclass" from within my model, and so it automatically creates the classes for my entity.
However, on the declaration of the class, I get this error:
Invalid redeclaration of "RoleName"
even though I don't have any other class with the same name.
This is because Xcode handles all that by itself. I felt it like a bit of trouble as the auto generated classes don't have all my properties.
So follow these steps to get this as it used to be:
Delete what ever classes you already made for core data.
Set class.Module as Current Product module
Set Class.codegen as Manual/None
Now select your entity and create NSmanagedobject subclass
You are all set
From Apple : Whats 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.
You don't need to manually create subclasses for NSManagedObjects.
I would suggest that you delete the files that you created with NSManagedObjects (Move them to Trash) and go to every entity in the DataModel Inspector under Codegen select : Manual / None and create than the Subclasses.

invalid redeclaration in auto code generate NSManagedObject Subclass Swift 3

Using Version 8.1 of Xcode.
Create an entity named "MapRegionObject" in .xcdatamodeld file.
Using auto code generator, click Editor on the navigation bar -> create NSManagedOject Subclass...
Got two files : MapRegionObject+CoreDataClass.swift and MapRegionObject+CoreDataProperties
Errors in two files showing in the screenshot:
MapRegionObject+CoreDataClass.swift
MapRegionObject+CoreDataProperties
Please help me fix this bugs, thank you so much!
In Xcode 8.1, before using the auto code generator, you must select the entity in your data model:
Then go to the Data Model Inspector tab:
Under "Codegen" select "Manual/Node"
After that you could create a NSManagedObject subclass without errors.
Alternatively, if you have already used 'Class Definition', you can go into your existing .xcdatamodeld file and set all current entities to 'Manual/None' under Codegen. Make sure to save your project (File -> Save), delete your existing Derived Data, clean the project, and then build. Resolved it for me without having to re-make my whole model.
I found this whole thing to be very confusing. You really do need to understand what's new in CoreData. Basically, the default is to automatically generate the class and the extensions for you in a place called "DerivedData" that's buried in ~/Library/Developer/Xcode/DerivedData where these classes and their extensions live, outside of your code source. Personally, not being able to open and look at them is weird to me, but something to get used it.
Basically, if you have an entity called "AppSettings" in your CoreData model, you can just use it without needing to generate the code yourself. If you want the code in your project, then set the Codegen property on the entity to Manual/None. Then do what you did before: Editor->Create NSManagedObject classes, etc. The files will wind up in your project.
The good news is that if you want to make custom extensions, just do that in your project. Xcode will blend the generated files, from their other place outside your project directory, with the files in your project directory.
1) clean the project (cmd + shift + K)
2) In the "data model inspector" for every created Entity set attributes for Class just as in the screenshot below
3) Generate code again (Editor -> create NSManagedObject Subclasses)
After that everything should work fine.
The problem is that you don't need to generate NSManagedObjectModel subclasses manually anymore.
ref: https://forums.developer.apple.com/thread/48988
Xcode automatically generates classes or class extensions for the
entities and properties in a Core Data data model. Automatic code
generation is enabled and disabled on an entity by entity basis, and
is enabled for all entities in new models using the Xcode 8 file
format. This feature is available for any data model that has been
upgraded to the Xcode 8 format. You specify whether Xcode generates
Swift or Objective-C code for a data model using the data model’s file
inspector. When automatic code generation is enabled for an entity,
Xcode creates either a class or class extension for the entity as
specified in the entity's inspector: the specified class name is used
and the sources are placed in the project’s Derived Data. For both
Swift and Objective-C, these classes are directly usable from the
project’s code. For Objective-C, an additional header file is created
for all generated entities in your model: The file name conforms to
the naming convention 'DataModelName+CoreDataModel.h'.
Close the project and follow the following instructions:
Reveal in finder your database .xcdatamodeld file.
on .xcdatamodeld file right click -> Show Package Contents, if(.xcdatamodel) is find again in the package again right click and 'Show Package Contents'. you should get 'contents' file.
Open 'contents' in text edit.
Command-F (codeGenerationType="class") and replace all matchings string with blank string.
Save and open Xcode project again.Everything should work well.
In Xcode 8.2.1 , Menu-Product-Clean,And every is ok, it's so verid.
Don't fight the with Xcode on this unless you really need to alter your generated properties, doing so will just leave you frustrated.
Think of the auto-generated class as any other class in your application. If you need to add functionality to your managed object class, simply change your class definition into an extension and extend your object.
change your class:
class MyManagedObject : NSManagedObject { /* implementation*/ }
to an extension:
extension MyManagedObject { /* implementation */ }
This isn't an answer. It's just explanation of what's going on with the selections
Make sure you see this moment for the Core Data Stanford course
Below is a transcript I wrote myself (It's not 100% accurate):
The default is class definition, if you choose this one. It will
generate that subclass and it will just work. You'll be able to access
your tweets as a class called Tweet. This sounds good. Btw if you do
this it will NOT show up in your file navigator.
The one we choose the most often is the category/extension what this
will do it will only generate an extension of the Tweet class. You
have to actually write the tweet class itself. The extension will take
care of making all the vars. Even when I switch to category/extension
again I don't get that extension showing up in the navigator. It's
kind of hidden from you.
And why do we like this one? Because a lot of times we want to add our
own code. Like in a Tweet, imagine you want to add a static method
that took data from Twitter and turned it into a tweet in the
database. Where would we put code? Well a great place to put that code
would be in the Tweet class...if there was such a thing...and the
extension is going to handle all the var business for you.
If you did choose manual/none for codegen. meaning don't do any
codegen, then you would be doing value/setValue(forKey:)...good luck
with that You're code is going to be a mess. [ie there is no
.propertyName = value ...you'd had to do setValue(value, forKey:
propertyName)].
Long story short, I'm not sure why but for some reason if you don't select the create NSManagedObject subclass then it seems to still work, but without showing what's happening under the hood. Very counter intuitive!
Then also watch this live demo of the Core Data Stanford course:
Now we know we want to access all this stuff not using
value/set(value:forKey:)...we want to have to subclasses of
Users/Tweets. And we want to have vars [ dot notation] for all these
relationships so we need that code to be generate. The way we do that
we just select the entity... and we go down here to CodeGen. This says
by default class definition. That means it's done it. It has generate
a class called Tweet. and It's going to work with var and all
relationships. That's not actually what we want. We want to select
this one [Category/Extension]. Where only create an extension to Tweet
and add the var stuff. That's because we want to write the class
Tweet and put our own code in there. It's very common to write our
own class. But you still want the var magic.

iOS Swift Core Data generate NSManagedObject with project namespace

OK, so I read that in Swift, we need to prefix our Core Data entity class names in the inspector with our project namespace.
Let's assume my project is called "MyProject", so for each on my Core Data entity in DataModel.xcdatamodeld I add "MyProject":
MyProject.Book
MyProject.Library
When I select the two entities in the Data Model interface builder and go
Editor > Create NSManagedObject Subclass
It only generated 1 class file called MyProject instead of the usual
Book class
Library class
That's how I normally do it with Objective C.
Is there an extra step with Swift that I'm not aware of ?
Looks like a bug in Xcode that Apple needs to fix as mentioned in the comments of this Stackoverflow post by Martin R:
Unable to find specific subclass of NSManagedObject
A PITA work around
I was reading this
http://jamesonquave.com/blog/core-data-in-swift-tutorial-part-1/
It seems like the way to work around this for now is to:
Before generating NSManagedObject subclass using using Editor, remove all the namespace prefix from entity class name
Select all the entities you want to generate NSManagedObject subclass for and generate them using Editor
Now add the namespace prefix back to all the entity class name and save the data model file.
Have to wait for Apple to fix it I guess =/

I can't use my core data model in two targets in a Swift project

The class name for entity models in the Core Data model has to have the app name prepended to it. So for an entity named User the class name in the model editor has to be MyAppName.User. This works fine until I added a second target to my project.
The new project expects the entity class names to be SecondAppTargetName.User. How do we support two targets using the same core data model? I tried prepending ${PRODUCT_NAME}.User instead, not expecting it to work. And it doesn't work.
Any ideas on how to share one core data model between targets and satisfy the need of Swift projects to have the PRODUCT_NAME prepended to the class in the model editor?
EDIT:
It appears from the Apple documentation here that adding the module name as a prefix to the class name in the model entity inspector is the preferred behavior. If so this seems like a gaping hole since it precludes multiple targets using the same data model. I still have found no workaround for this yet. Some posts here on SO have indicated that using #objc(ClassName) in front of the Swift class definition for the managed object will do the trick, but I haven't been able to verify that yet.
It turns out that the answer does appear to be adding the #objc(ClassName) directive above the class definition in the Swift file as noted in this StackOverflow answer about a related problem. At least it is the answer at this stage with XCode 6 beta 5.
So for an entity class called User you would need:
#objc(User)
class User: NSManagedObject {
...
I have tested this in a two-target project and removed all the prefixes from the model entity inspector and it works. I'm wondering why Apple would include the prefix requirement in their documentation since it imposes a restraint on multiple targets using the same core data model. It appears the #objc fix is the proper solution or maybe just a temporary solution during this beta stage.
I fixed it by using target this way. I am not sure if this is the correct way. I would appreciate corrections. This way it created two different stores and corresponding files.Both app can be on the same device using two different stores.
if(currentTarget==XXX){
storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"Partner.sqlite"];
}
else{
storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:#"PartnerNew.sqlite"];
}

Resources