Correct way to update Objective C project for Xcode 8 Core Data NSManagedObject subclass changes - objective-c

I took a break from coding for a few months and came back and discovered the changes in CoreData with Xcode8/iOS10/macOS Sierra.
I have been trying to get my head around the new NSManagedObject subclass generation in Objective C but there is very little out there on the web. I have a few things I need clarifying before I start butchering my project and messing things up completely but first, some things I have discovered from poking around that might be useful to others out there...
Where things are
Automatically generated files live buried deep in the DerivedData folder. Look in USER->Library->Developer->Xcode->DerivedData->ProjectName-lotsOfRandomLetters->Build then keep opening folders until you find DerivedSources->CoreDataGenerated.
Automatically generated files do not appear in your project folder or navigator, although if there is an error in one Xcode will display the source for you.
Things Xcode generates
There are three codegen settings - manual/none, Class Definition, and Category/Extension.
When an entities codegen is set to manual/none (which was the old behaviour) creating the NSmanagedObject subclass using Editor-> Create NSManagedObject Subclass generates 4 files inside your project...
Entity+CoreDataClass.h and Entity+CoreDataClass.m and
Entity+CoreDataProperties.h and Entity+CoreDataProperties.m
(previous version Xcode 7 generated Entity.h, Entity.m,
Entity+CoreDataProperties.h and Entity+CoreDataProperties.m files)
If the entity's codegen is set to Class Definition, Xcode generates these same 4 files automatically in the derived data folder - not the project, These files are then marked with a comment telling you not to alter them.
Xcode generates 2 files if the entities codegen is set to Category/Extension. These files are marked with a comment telling you not to alter them. These are...
Entity+CoreDataProperties.h and Entity+CoreDataProperties.m
These 2 file are expecting a Entity.h file to be in the project and will show an error in Xcode if absent. This is the one time that you will be able to see the source for one of these files within Xcode.
Whats in these files
The + CoreDataProperties files appear to be the same as those generated previous version of Xcode generated files except for one addition. They contain all the attributes / properties for the entity / NSmanagedObject and the methods to handle entities that have a one to many or many to many relationship. The new addition is a method for fetchRequest subclassing NSmanageObject's new fetchRequest method.
Questions
1) Is Class Definition now the obvious and best choice for codegen when you don't have any extra properties/functionality to add to a NSManagedObject subclass, as it automatically updates the files for you (when you save the project with cmd-s)?
2) The naming of the files with +CoreDataClass follows the convention for a category on a class, which would imply there should be a class for this to be an extension on.
Am I right in assuming that the Entity+CoreDateClass .h/m files are a straight replacement for the old Entity.h/m files? and that its not actually a category, despite the file name?
3) For new NSManagedObject subclasses should I be importing Entity+CoreDataClass.h rather than Entity.h?
4) If I want to uncluttered my project by removing most of my NSManagedObject subclass files, do i just delete the files in Xcode and set the entities codegen to Class Definition or ...
is there magic under the hood that looks for the entity+CoreDataClass when you try to #import entity.h or will I have to go through and find every reference to #import entity.h and change them to #import entity+CoreDataClass.h ?
5) Am I right in assuming that if I want a NSManagedObject subclass where I want to add a property and a method that i should set codegen to Category/Extension?
6) If I choose Category/Extension I have to create my own NSmanagedObject subclass file, its just entity.h not entity+CoreDataClass.h?
7) If entity+CoreDataClass.h is the new accepted naming format for the entity.h file why does the generated Category/Extension file look for a plain entity.h name file instead of a entity+CoreDataClass.h file? Is this just an inconsistency on Apples part and something I should just accept or am I missing something that I should know about?
Thank you.

Okay - quite a few people looked and no answers so i'll try and answer myself.
1) Yes - if you don't need to add extra properties/functionality to a CoreData entity, go with Class Definition. This creates 4 files:
Entity+CoreDataClass.h and Entity+CoreDataClass.m and Entity+CoreDataProperties.h and Entity+CoreDataProperties.m but you'll never see them as they are hidden away from sight deep inside the derived data folder. If you need to check on a attribute name you can look in the core data editor as you won't have access to these files.
2) Entity+CoreDateClass .h/m files are a straight replacement for the old Entity.h/m files. Despite using the file naming convention for a category, they are not categories, don't let Apple's naming system confuse you. Look inside the file and the class is defined as Entity not Entity+CoreDataClass.
3) For new NSManagedObject subclasses (autogenerated with the 'Class Definition' option) import Entity+CoreDataClass.h rather than Entity.h. After all' it's the file you are importing not the class defined inside. When using the class its just Entity not Entity+...
4) If you decided to declutter your project, by deleting your NSManagedObject subclass files then switching entities codegen to 'Class Definition', you will need to go through the project and change all the import statements that refer to them by adding +CoreDataClass to the file name. Fortunately its not that big a deal as Xcode will have flagged them all up as errors anyway so they are easy to find.
5) Yes - if you wish to add properties or functionality to a NSManagedObject subclass use the codegen "Category/Extension" option.
6) If you choose Category/Extension you have to create my own NSmanagedObject subclass file, name it Entity.h. Do NOT name it Entity+CoreDataClass.h because the autogenerated Entity+CoreDataProperty.h is looking to import an Entity.h file.
7) Yes, this is just a naming inconsistency on Apple's part. Don't let it throw you, like it did me.
And finally , don't forget...
if you go down the route of using codegen ->Category/Extension, if you add an additional relationship to the entity, you will need to update your Entity.h file. For example if you added a relationship to a NSManagedObject subclass called Car you would need to add the #Class Car; to Entity.h.

Related

Migrate XCode 7.3 CoreData Model to XCode 8

I run into a problem with Xcode8 and automatic CoreData NSMangedObject creation.
The toolversion is already downgraded to Xcode7.3 and the entities are in codegen mode manual/none.
I added a new attribute to an entity and created the NSManagedObject subclass over the Editor->Create NSManagedObject Subclass.
XCode now generates the Entity+CoreDataClass.h/m and the Entity+CoreDataProperties.h/m Files.
Does this mean that I have to change any #import (no Problem by search and replace) or is there an other way to get the old Entity.h and Entity.m Files?
What about my existing code in the Entity.m files, do I have to copy & paste it to the new Entity+CoreDataClass.m file?
In my opinion the code generation is buggy. If there is a relation to other classes the import in the Entity+CoreDataClass.m file is wrong.
The class imports the old Entity.h files...
Perhaps anyone has an idea. If there isn't any other possibility this could only be a joke by Apple....

How do I get the XCode Project URL programmatically?

I'm curious if there is a way to programmatically get the location of the .xcodeproj package within an Objective-C (or Swift) class contained within that package. I'd like to make a simple utility that puts files directly into the containing folder based on various app events, but I would rather avoid hard coding the path.
Essentially I want to create a target (and a reusable class) that builds swift files for NSManagedObject subclasses based on the Core Data model present in the app.
I found out the trick here is to add an item to your plist file that contains value ${PROJECT_DIR}, then you can get the location in your code with
var projectPath = NSBundle.mainBundle().infoDictionary.objectForKey("com.myapp.project_dir") as String
This assumes the plist key is "com.myapp.project_dir", of course.

How to create a .m file corresponding to a .h file in xcode

When I try to create a .m file from the file menu, it prompts me for choosing a template from the several types mentioned - Objective-C class, Objective-C category, Objective-C protocol, etc.. Which one should be preferred?
I am fairly new to Objective-C as well as Xcode, so pardon me if this question is too obvious.
You may have to add Objective-C class and rename the new.m alone
to match your old.h and remove the newly added new.h file.
Create a new Objective-C class and copy your code from old.h to new.h file
Update as per comments: I see you are trying to add .m for the MAC sdk library, which is not possible.
You may have to consider using Categories extending the existing class methods.
What is “category
Customizing Existing Classes
If you want to create just an empty .m file, you can do so following these steps (Xcode 5.1.1):
In your Xcode project, go to File --> New --> File...
Select Other --> Empty
Click on Next
Type a name for your file and be sure to finish it with extension .m
Click on Create to save it

ViewController.h and ViewController.m Prefix

Okay so I have just started programming in Xcode 4.3. All of the books I use to practice coding in Xcode the Examples show the ViewController.h and ViewController.m take the name of the project name as their prefixes. For instance... If the book named the application "Calculator" , in the examples the View Controllers are both named "CalculatorViewController.h" & "CalculatorViewController.m". Am I doing something wrong here??
I apologize if this is a newbie question, but Ive tried doing almost everything to figure this out!
Please help me
When you add files into your project (class .h and .m files) there is not an automatic mechanism that prefixes these files for you, based on your product's name. You have to do it manually.
The reason you see that pattern in the books is because is a common practice to prefix your files with some initials so to namespace them and avoid conflicts when working with someone else's code (that's why Apple's classes are prefixed with an 'NS').
Xcode 4 even lets you choose that prefix when you create a new project, so if you type in your application name there (for example 'Calculator') the files that will be created initially for you by Xcode will be prefixed accordingly (so you'll get a CalculatorViewController for example), but for any other files that you add, you have to explicitly prefix them as you like. I hope that this makes sense.
UPDATE:

Should there be a link between the class name and the file name in which it resides?

OK, so I have 2 files (header and implementation) named MyLib.h and MyLib.m, inside those 2 files I have multiple classes, protocols and interfaces but none called 'MyLib'. Now, everything works just fine, I have only one problem, xCode doesn't show me any class hint except for MyLib (which btw is only the name of the file, there is no MyLib class).
Now, this small problem made me think about it, is this a bad practice? Is is better to have a file for each class and if yes, why?
I just created a .h file with a different name from the class inside it, and Xcode gives me the completion for the class name, not the file name. Have you #imported the header wherever you're trying to use it?