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:
Related
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.
I'm helping on an iOS project with lots of methods and definitions common to many different classes in the AppDelegate. So, in each of those classes, in the .h file, I use #import "AppDelegate.h". This works fine until I need access to one of those classes that already imports the AppDelegate into another class that imports AppDelegate. At this point, I get a Duplicate Interface Definition error for AppDelegate.
Ok, so that seems fair. I'm already importing AppDelegate into a file that I'm importing, so AppDelegate is getting imported from two different places. So I remove the AppDelegate line, and everything is fine.
But what happens when I need to import two classes that both need to import AppDelegate?
I have a very specific problem that I'm trying to wrap my head around, and I know it is being caused by something that has to do with this, but I'm not sure what. So I'm hoping if I figure out how I'm supposed to be handling this sort of importing, and sort everything else out, and hope that this solves my problem. So to put this in more concrete terms:
I have ClassA.h, ClassB.h, and ClassC.h. All have #import "AppDelegate.h". When I need to use #import "ClassB.h" in ClassA, I remove the #import "AppDelegate.h" line from ClassA. Everything works smoothly. But what happens if I also need to #import "ClassC.h" into ClassA, and but ClassB and ClassC NEED to have the #import "AppDelegate.h"?
EDIT:
I tried the exact scenario I described above in a clean project, and it built fine, so there is something else at play. But what I can say with certainty is that when this issue came up previously with this project, it was a duplicate interface definition of AppDelegate, and when I removed the #import "AppDelegate.h" line, the error went away, and I still had access to the AppDelegate.h methods and enums through other imported files.
The best prevention and cure for this is to follow some guidelines on when to import from a header file. As a general rule, never import from an Objective-C header except in these cases:
You need to extend a class declared in another header.
You need to declare conformity with a protocol declared in another
header.
You need to refer to a non-class, non-protocol type defined in another header in the public methods and / or properties. To refer to protocols and classes, forward declare them with #class or #protocol, like #class ClassFromOtherHeader;
Every other #import should go in your implementation. My recommendation is to start moving all your #import statements out of headers and into the implementation files according to these rules. Start with the files you think are at the root of the problem and move outward. This will fix your problem and give you the side benefit of clearer code and faster build times.
For me none of the above answers were helping, nor did the answer given here work.
What fixed it for me was closing Xcode, going to ~/Library/Developer/Xcode/DerivedData and deleting all of the derived data associated with this project. After that I reopened the project and it was working fine.
Hope that helps someone!
In my case, none of the solutions mentioned fixed the issue. Xcode was reporting a duplicate interface for a class I rewrote in Swift. Somehow it kept pulling in the Objective-C header file for a class that wasn't directly referenced in the project.
I opened the Terminal, cd into the project directory, then ran the following to track down any files that were including the class header:
grep -nr ProblemClassName.h .
It turned out that the bridging header included an obsolete file that wasn't even referenced in the project navigator. That in turn was importing the header files referenced in the Xcode error, that were also not included in the Xcode project navigator. Now I know to not rely only on the Xcode project navigator for files referenced by the error.
tl;dr Double check the bridging header to ensure that all files that are imported there should be there and are not importing headers that are in-turn importing the problem headers.
I found that a project had a subproject and instead of referencing the includes in the subproject with the proper syntax:
#import <SubProject/Filename.h>
It was directly importing them
#import <Filename.h>
This was only possible because the path of the subproject was included in the "header search paths" of the main project - which is the wrong way to do business. So I deleted it from there.
The subproject should copy the needed included files in its "build phases - copy files" section (which was already happening actually), and the proper form of import that uses the Subproject/Filename.h syntax should be used.
Fwiw I started getting this seemingly at random - for me the fix was to do Product->Clean and it magically went away.
For me, I forgot to include parenthesis in interface definition in m file.
I created a new Xcode project (iOS application, Tabbed Application).
Now I'm seeing one sample code that Xcode generated for me (that I did not touch at all) and of course, it works on the iPhone simulator.
I am going through the code and though I'm seeing references to the .h files, I do not see any reference in any of the created files to .m files. (as in
#import "MRTAppDelegate.h"
#import "MRTFirstViewController.h"
#import "MRTSecondViewController.h"
Does the compiler just process whatever .m files you add to the project? Is there a list where they are all accounted for?
p.s. As it is obvious I also have little Objective C background, whatever I could carry from my university C classes.
if you go to build phrases -> compiled sources all the .m as specified there.
You're right on the basic assumption that Xcode will link the header and implementation for you. Just make sure you're added the .m file to your build sources and Xcode will do the rest.
You're also always going to #import the header file, and not the implementation file, in other classes.
So I'm creating a new file, a subclass of a UIViewController via the Xcode wizard that pops up through new > file.
I'm naming the file "747ViewController" and it spits out the .h/.m files fine.
However inside the files, the interface and implementation names are odd:
They show up as #interface _47ViewController : UIViewController and #implementation _47ViewController
Are you not allowed to start with a number or something? Should I leave it or rename it to what I want it? Thanks
That's correct: just like in C and C++ your identifiers can not start with a number. The workaround from Xcode is correct: Unlike Java, the source file name and the class name do not have to be the same.
Just as background, there are no compile-time errors or warnings in the subject project "Project".
There are numerous occurrences of using the same instance variable name in two (or more classes). In the following, I'll use the variable name "index" as an example. It appears as an instance variable in class1 and class2. The variable has different but similar meanings in both classes, hence the use of the common term.
I define index in the header file for both class1 and class2, for example:
#interface class1 : NSObject
{
int index;
}
...
Repeat for class2.
When I build the project, Xcode reports:
Duplicate symbol _index in /Project/build/Project.build/Debug-iphonesimulator/Project.build/Objects-normal/i386/class1.o and /Project/build/Project.build/Debug-iphonesimulator/Project.build/Objects-normal/i386/class2.o
Changing the occurrences of "index" to "indexnotverycommon", reports the same error with the new name.
Changing the occurrences to "index1" and "index2" respectively gets rid of the error. Xcode then reports the next duplicate it finds during linking, and so on, and so on.
I can continue the renaming process although I'd rather not, as I'm concerned that there is a more pathological underlying issue.
Any advice or question is appreciated.
index is a also a C function and thus a very unfortunate name in Objective-C.
This article describes why it's not a good idea to use index as a name.
I'm not sure why you get duplicate symbols though.
I figured it out using the Xcode find-in-project feature. Thanks for the advice about index.
don't #include or #import .m files. Just add those .m files into the Target | Build Phases. Don't add .h files into build phases, but #import .h files wherever you need those functions.
The compiler knows that it's just a header file "for information only" and that the bodies of the functions will be available when it will compile the .m files and put them all into 1 executable
The header file contains only forward declarations. Compiler knows that the body is either defined in another file or is in a lib linked to the project
The tip to check for an #import "Xxx.m" instead of the correct .h worked.
A quick workspace wide search for "Xxx.m" spotted the error in the include which was causing the link error.