Default file:
#import <Foundation/Foundation.h>
#interface MyClass : NSObject
#end
My understanding is pre-compiled headers are included in every file. Why doesn't this import just go into the pre-compiled headers?
There is no guarantee that every project have a .pch file that import Foundation.h so Xcode need to generate it to make sure new files always compile.
Also some people think it is good style to include header even it is already included in .pch file. Because you know exactly what headers are needed by this file. It also allow people to disable prefix header if needed.
My Xcode 5 doesn't appear to be including it in every class (it is included in the .pch file). I agree with you that this makes more sense than including it everywhere. The answer to your question is probably "an oversight on Apple's part" :)
Related
Just wondering -
When you start to type #import "
Xcode suggests .m files and .h files. I just had a few hours of frustration after mistakenly importing .m file.
Is that a bad design? Can you import .m files?
You can import any files. #import is just a preprocessor directive that basically says "include contents of the file I tell you into the current file". There are some include guards as well, but the import does just that - it imports the file you tell it to.
Importing the header with .h file is probably more of a convenience/convention (please don't beat me for this, I'm just guessing) unless there's some C/C++ standard that says otherwise.
I included in my iOS project a widely used UIImage category to handle PDF, and got some compilation errors. This raised several questions.
Q1: Why would Xcode (or actually the LLVM compiler) not give any warning on a header file that is including itself ? I don't know if this has a special meaning in C or Objective-C that would prevent it from being seen as a typo ? In my example, I believe that a mistake was made and Foundation.h was probably the intended include:
In the category file NSString+MD5.h I found:
#import "NSString+MD5.h"
#interface NSString(MD5)
- (NSString *)MD5;
#end
The corresponding .m does not include the .h. (Link is "Here")
Q2: I got the compilation error because I started from an Apple project that doesn't NOT include the Foundation framework (AVCam 3.1 for iOS) ! So NSString was undefined. I'm a bit puzzled by this but linking with the foundation framework in xcode is like including all its headers ? I would expect again some warning at least ?
Thanks for any explanation on this probably very basic C topic.
First of all, in Objective-C, we #import, which is different from #include. While #include will attempt to include any file you list, #import will never double import any file. I imagine that this explains why there's no problem with a .h file trying to #import itself. It's not correct for the file to import itself, but because it's an #import, it won't actually cause any issues.
As for the .m file not importing it's .h, in this case, it doesn't actually have to. It's a good idea, out of habit, to always import the .h file, and any files generated by Xcode will do this automatically, however it's not always necessary. It's only necessary when the .h file has declared something that the .m has to know about. For example, a #property that you intend to use. You've declared it in the .h so it'd have public access, but if you intend to use it in the .m, the .m has to know the #property has been defined. Additionally, if you've #imported some files in the .h that the .m needs and you don't want to import them again in the .m, you'd need to import the .h (although it's generally going to be better to just import them in the .m.
Here, the .h simply defines the exists of a method that returns an NSString * and is called md5 and takes no arguments. This means that anything importing this .h file can call this method and Xcode won't complain about the md5 method not existing. The corresponding .m file implements a method that coincidentally matches the one the .h defined. If you deleted the .m file, your program would almost certainly still compile just fine... but you'd hit an unrecognized selector exception when you go to the point that md5 was being called--despite Xcode not complaining about it. With the .m in the project, this exception isn't hit. The program figures out at run time which method to execute.
And finally, as for not including Foundation.h, every iOS project created by Xcode has #import Foundation.h and #import UIKit.h in the precompiled header file. Any other file in your project with these imports is just redundantly importing the file, as it's already been imported by the .pch, but because of the magic of #import (vs #include) it's not actually double imported.
If you're working with an iOS project that doesn't have these imports in your .pch, your best bet is to just stick them in the .pch.
If you're opposed to this for some reason, the best way to fix this md5 file is with this simple line:
#import Foundation.NSString;
I am facing an issue, Currently i am using xcode 5.0, when i am importing clasess from prefix.pch then it dose not give suggestions on appdelegate.h file. But it gives suggestion on other view controller's. I have googled about it and find if we define macros in prefix.pch then this problem occurred. Still after removing the macros it did not give suggestion on appdelegate.
Suggestios means if i try to write
#property(strong,nonatomic) UINavigationController *navControler;
After writing #property(strong,nonatomic) UINav xcode did not give suggestion. But if I remove all the import statement and macros from prefix.pch file then xcode give suggestions on appdelegate.
From my point of view, rather than finding a workaround, I want to put some light on the actual problem.
So when you want to add something in .pch (pre compiled headers), it means you want to use the content of files before your program is actually being compiled & build. In simple words the headers included in pch acts as a stub code, a base code or may be a code that is meant for using as it is intact.
So if you have already included appDelegate.h file in .pch & writing some code in appDelegate.h file, then the compiler is trying to use 'appDelegate.h` from .pch as a pre-compiled information. And may be it is resulting in a indefinite sate of Xcode background processing, which is not allowing to show the drop down helps in the file which is already pre-compiled.
To me it looks like app delegate.h in .pch is not the right place. Where ever you want in your program, you can very well include appDelegate.h file. However it is also a signal of bad Class Design approaches.
Also, if you want to add #define statement & other macros in .pch then it is not the right approach. The right approach is :
Make a simple .h file, say constants.h
Add all your #defines & macros here in constants.h file.
Add the #import "constants.h" in your .pch file.
That should solve your problem.
Hope that helps.
I added two files to a Xcode 5.1 vanilla single view project:
table.h
struct group {
int size;
};
table.c
#include "table.h"
and got this error:
Semantic issue
table.h:2:8: Redefinition of 'group'
"Previous definition" is:
iOS 7.1 > usr/include > grp.h
I am wondering why this grp.h is automatically included in my project. How can I not include it?
grp.h is one of the standard Unix-level files which defines some of the basic data structures; in this case, struct group is what gets returned by low-level C functions that deal with user permissions.
As for the question of why it's included in your project: When you create a new project in Xcode, it creates an include file that implicitly gets included in every .m or .c file in your project. In the project I just created to try this out, it's in the file browser in a group called Supporting Files, named something like [project]-Prefix.pch. Mine has the following contents:
#import <Availability.h>
#ifndef __IPHONE_5_0
#warning "This project uses features only available in iOS SDK 5.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
That second to last line, #import <Foundation/Foundation.h>, then includes all the built-in Objective-C objects like NSObject, NSArray - and a bunch of things that work with the filesystem, and therefore need to be able to deal with permissions and group membership. One of those is then including grp.h.
So, back to your question - you can change your .pch file to not include Foundation/Foundation.h, and then manually include it wherever you need it.
But that will end up slowing down all your builds. The .pch file here is special; Xcode compiles it once and saves it in a binary format, so it doesn't have to parse the many thousands of lines of C code it expands to for every file you build.
My advice? Name your structure something else.
Normally of course it would be easier to change the naming of your struct, but as it comes from another library, here is my solution for you.
Turns out that if you allow your .pch file to include any of header files from iOS 7.1 > /usr/include then it will reference (include?) many more, including grp.h which causes the problem in your project.
So for example, if your .pch files contains this:
#import <Availability.h>
Then grp.h will cause the conflict.
If you comment out this line (and don't include any other headers from "iOS 7.1 > usr/include") then your project will compile.
As a test you can comment out <Availability.h> and add #import <cpio.h> and the result will be the same (although cpio.h is very small and don't reference any other header files).
I am not that good at understanding internals of compilation, so I can't explain why this happens but I traced down the issue to this file:
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.1.sdk/usr/include/module.map which seems to group together various Darwin header files.
Both iOS 7.0 and iOS 7.1 have this file while iOS 6.0 doesn't (which may explain why the same code worked on earlier iOS versions).
The good news is that although you need to remove /usr/include headers from your *.pch file, you can still include them in files where you actually need them and it won't break the compilation. That's probably because although the grp.h will eventually be included in those files, it won't be included in your table.c
grp.h has already declared a struct named 'group',
so you just need to rename your 'group' struct and everything will be ok.
(for example 'my_group')
I am just wondering, is it good practice to include commonly/mostly used header files in .pch file?
e.g Most of files required below headers
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
So instead of each file should have, is it good practice to add those in .pch file?
.pch file
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <MostlyUsed.h>
#endif
I found some disadvantages of this,
1) Dependancies get hidden.
2) Source files can not be copied directly.
It will be great if you guys provide some inputs on this.
Thanks
Yes you can do it.
Even it reduces compile time.
An Extract from In Objective-C, importing same headers in every class make compile time longer?
In general, newly-generated iOS projects come with this functionality,
which is called a precompiled header or prefix header, and is a file
that has the extension .pch.
You can throw all the headers you want in there and Xcode will
pre-compile it before it builds anything else, and use it to compile
the other compilation units in your project (e.g. .m files).
Using a precompiled header may or may not increase compile time; in
general, it reduces compile time, as long as you have a lot of common
headers and/or a lot of source files.
However, it's not necessarily good practice to treat the pre-compiled
header like a big dumping ground, as your compilation units can form
implicit dependencies on all sorts of stuff when you may want to
enforce loose coupling between components.
It is certainly a good practice as it reduces compile time and code is lot more manageable by doing so.