In Objective-C, do I need to import every h file to see my object hierarchy? - objective-c

I've created an 3 objects, and chained them together:
Questionnaire object - which contains a
NextQuestion object - which contains an
Answer object - which has an text property.
In a ViewController, I want to be able to call:
NSString *thisAnswerText = Questionnaire.nextQuestion.answer.text;
However, to do this, I have to import all three files into my .m file
#import "Questionnaire.h"
#import "Question.h"
#import "Answer.h"
Is it necessary to import each of the objects that I use in each .m file? Or is there something I can do which means I only need to import the top level item and all it's children are automatically referenced?
NB. I know that I can add all three to the Prefix.pch file, but I was wondering if I'm missing some trick to Objective-C which allows me to declare one item and it's child objects become imported automatically?
THANK YOU!

When you import a .h file any imports within the .h file are also available. You may need to clean and rebuild but they should be available. So in your case no, you should be able to get away with importing the Questionaire.h only.
Also if you're app depends on those custom classes and they will be used all over the place, it can be a good idea to import them in your .pch file and they will be precompiled for all your classes.

Is it necessary to import each of the objects that I use in each .m file?
Not in all cases, but if you message an object, you should ensure the compiler sees its declaration -- just because ObjC is a very dynamic language.
Or is there something I can do which means I only need to import the top level item and all it's children are automatically referenced?
Yes, you could add an #import in any header (of course, the must be compatible with the translation). However, adding #imports should be minimized because #importing the world will increase your build times and introduce a bunch of dependency.

In the public header files for your interfaces, you should forward-declare as much as possible and only #import what is really needed. This will help to keep build times down. In your implementation files you can import anything you need.
Sometimes for usability's sake, you may which to collect multiple headers into a single "MyFramework.h" file so that you don't have to add 5 imports everytime you use a class. You should be careful with this however, because it can increase build times if the header is imported in many places.
You may also want to think about adding common imports to your prefix header (.pch) which can be precompiled by Xcode to improve build times a little.

Related

How to import a lot files at once?

Say I have a ton of small classes that I want to import all at once, is there a way to define a file that is literally just a list of imports and then only import that one file instead of having a long list of imports for each class?
Your suggestion will work fine: you can create a header file, and put #import "..." directives in it. Then you can include that header in all your files as needed.
Xcode provides an even better solution - the file called Prefix.pch. Instead of creating your own header, put the #import directives there. The result would be that all your files will implicitly include the files that you import in Prefix.pch - you wouldn't even have to import them.

I need to create separate file for all the constants of my project

In my project I have a requirement to create separate file for all constants that i am using in separate classes in the same project.
I seen some examples but they are saying about creating in '.h' file and again they are implementing them in '.m' files. But i need only '.h'file to create all constants and i have to use all those constants by importing that '.h' file in every class of my project.
ADD a new file.
Right click on the file inspector
choose New File
The pop up window select ios>C and C++>HeaderFile[Figure]
Give name Constants
Add #define OK #"OK"
Go to View Controller include file in header #import "Constants.h"
OR Define in pch file ,so that all View controllers can access the file
In viewDidLoad NSLog(#"%#",OK);
You can create .h file and use #define to create constants and then include your file to prefix file of your project. Though I prefer to use extern constants which you declare in .h file and define in .m file. This help to track possible warnings in your code at compilation time.
You've pretty much answered your own question, to the point where I'm not sure exactly what you're asking - you can just create a header file (.h) with your constants, and import it into your other classes. You don't need to create a corresponding implementation (.m) file. If you're using your constants throughout your code you could import them in your prefix header and have them automatically available.

how to make methods in category classes available to other classes?

I want to use a class I got from iosframeworks.com called UIImage+ProportionalFill. I know it's a category extending UIImage, but when I try to use one of its methods in another class I get a message saying no visible #interface for UIImage declares the selector 'nameOfWhateverMethodIWantToUse'. I'm not surprised to get an error, since there must be more to using it than dropping it into XCode, but how do I make the methods in the new category/class available to other classes?
You just need to import your category in the class you like to use it...
#import "UIImage+ProportionalFill.h"
I usually do this in the header file.
The compiler needs to be able to see the declaration of the methods, which should be in the category's header file. You must import the header file wherever you want to use the methods.
You need to #import the header containing the method declaration(s) in each file that uses said methods.
Note tha the methos should be prefixed; i.e. -JDnameOfWhateverMethodIWantToUse.
Note also that adding categories to framework classes willy nilly can easily lead to a rather awfully architected application that becomes difficult to refactor/maintain.
Based on what you said, I think you just forgot to import it.
#import "UIImage+ProportionalFill.h"
Write it on the top of the .h file of the class where you want to use the method.

Getting "Duplicate Interface Definition" error, definitely has to #import ing header files

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.

Importing into .h versus .m

Is there a difference between importing something (e.g. #import "JSON.h") into the header file versus the implementation file?
If you #import it in the header, then everything including that header gets it. You may find that useful, in that you don't have to #import it again in other places, but my preference is to #import things only where necessary, to minimize dependencies and make builds faster.
I think if you do it in the header file, you save your self some trouble later on in case you reference a class which is defined in the imported file.
In other words, if you import "JSON.h" in the header file, and there's a JSON class (hypothetically) that you will use in your header file (in the interface), then it would save you from having to do the #class directive at the top. Then your implementation file will also be fine since it would import the header file, which itself imported the "JSON.h" file
Basically I think it would be neater and would be more like objective-c if you import the required files in the interface file (.h). As you've probably noticed, interface files are usually short and concise, allowing you to get a quick glance at what a certain class is about and what it does. If you import your files there, you can also see what files/classes it relies on more easily, saving the implementation file (.m) for the actual 'meat'.