When should I import a header to Prefix.pch? - objective-c

I've heard importing a header to Prefix.pch can improve performance as it will load the header once, instead of on each instance. So when is a header imported enough times in a project to warrant being included in the Prefix.pch? A dozen times? Several times? Just twice?

I typically add a header to Prefix.pch if it is being #imported into more than 3 classes. I don't think there's a rule of thumb - it depends on your own standards for what you consider clutter, elegance, how globally the code is used etc. For example, most of my projects have a Utilities.h and Utilities.m where I declare helper functions used in many places. I always add Utilities.h to my .pch.

I tend to avoid the temptation of chucking too much stuff in the .pch. In particular, it obfuscates the dependencies in your code. Suppose you want to see where your code is using AFNetworking lib (for example): You search for the #import statements, and then see that the .pch file imports it, which tells you... nothing.
If when using a module/lib you usually import a number of related header files you can create a new header file that just imports the glob of related headers and then import that instead.

Related

How do inefficient imports affect your project?

AppCode has a feature to "Optimise imports".
It will take redundant or unused imports and remove them and reshuffle them etc...
I can see why it can be done... If you have 3 files A, B and C...
A imports B
C import A and B
In this case you can remove the import of B in C.
But what does it do to the project when these redundant imports build up? Can it slow the build? Does it affect the product?
In the case of redundant imports, it's mostly to reduce code noise (i.e. unneeded lines of code). There isn't a dramatic additional cost to importing the same file twice. include does have a non-trivial cost because it has to open and read the file (even if it uses #ifdef guards), but import tries to avoid that. Even so, there's a small cost there.
Importing a file that you don't use can have a large build-time cost. In C-like languages, importing means "read the whole file and all of its included files and parse them right here." That can be very expensive. There are some tricks to avoid it being exactly that bad (particularly precompiled headers), but it's bad. So getting rid of unused imports is definitely good for build times.
Neither should have any impact on the final product. If it did, then AppCode would be removing a header it should not have removed.
Some of this changes with the new #import syntax, which doesn't require reading and parsing all the header files for modules. But you'd still want to avoid importing headers you don't need for tidiness if nothing else.

Should I put all header file into Prefix.pch?

Is it recommended to refer to all my header file in Prefix.pch, and then I do not have to type #import headers during development?
I wouldn't recommend this.
The main reason is, header files can change in the course of your development. If you change one header, it will cause the pch to dirty, have to be rebuilt, and now your entire project will rebuild. That's quite time-consuming, and works counter to the whole reason for pch files.
Same thing if you create a new header file, add it to the pch, and now that triggers and entire rebuild.
But there's no single answer here. You may have a 3rd party library that will never (or rarely) change, is quite header-intensive, and so precompiling it may be a way to reduce build times. Experiment and see.
Pre-compiled header files were brought to serve one purpose: to make compiling faster. It is compiled and stored in cache, and automatically included in every source file during the compilation time. Its like each source file does,
#import "Prefix.h"
This can be handy for project-wide #defines. (FYI, #defines are a code smell)
Xcode quotes:
Precompiling the prefix header will be most effective if the contents
of the prefix header or any file it includes change rarely. If the
contents of the prefix header or any file it includes change
frequently, there may be a negative impact to overall build time.
More clear explanation is here
Please keep this in mind when you #import source file header in .pch. As a tip, you can use Prefix.h for #import of constants and utility source files.
From a standards perspective, your includes should be as minimal as possible. Indeed, you shouldn't include anything you don't require for compilation into any file. So, in each of your .h files you should primarily include the superclass and use #class for all other references, then include only in your .m files. This gives the clearest information about the requirements of each class / file and minimises circularity issues.
You should add header file to Prefix.pch just if you need that file/class in most of your other classes. If you need the header file just in one or two other classes it's not point to add it to .pch because it will takes more time for compiler to compile the files and it will happen every time you want to run your project.
I add all the headers to Prefix.pch, and I have to claim life is much easier since that time. I just do not have to import always headers, believe me, life is much easier. :-)

If UIKit is imported in the PCH file, then why is it imported again in each file?

If #import <UIKit/UIKit.h> and #import <Foundation/Foundation.h> are both found in our `ProjectName.pch' file, making them globally imported, why are they automatically added to the header file when Xcode creates a new class?
The .pch is there as a compile time optimisation, personally I recommend making sure that classes can still build without a pch (so still import into h/m's manually), so that it can A) build without and B) so that if you re-use code, you can easily see its dependencies.
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.
Only Apple knows for sure.
Best guess: Apple can not be sure that the imports are in the pch file for all projects or that there is even a pch file. This by having these implicit imports compiling can be guaranteed.

Objective - C Static Library and it's public headers - what is the right way?

I'm building a static library that will be used in multiple iOS apps.
In parallel i'm working on one of those apps using my library.
During development I get at least once a day an annoying error about header files from the library not being found (in my app project).
I learned that when building a static library, headers can be either Public, Private or Project
I'm guessing that every header that I want to expose in my library should be Public.
My question is, what is the best way to manage these public headers? should I create one main public header file with #import to all my public headers?
Can Xcode generate such file for me?
Another major question is what is the recommended value for Public Header Folder Path setting?
My major goal is that future projects that will use this library, will be able to do so with as less configurations as possible (Adding linker flags, changing User Header Search Path etc.)
Thank you very much.
About public/private/project headers, here is a previous answer just in case
=> https://stackoverflow.com/a/8016333/1075192
Most of the time, C/C++/Obj-C libraries and frameworks have one main header including all the other ones. Cocoa frameworks follow this path for example.
To declare a CAAnimation with QuartzCore framework for example you could do this:
#import "QuartzCore/CAAnimation.h"
or
#import "QuartzCore/Quartzcore.h"
"QuartzCore.h" is actually only composed of a header guard and includes of all the other headers of the library.
In my opinion, It's actually better to use the first one as it doesn't include all the declarations you don't need. But most of the time we choose the lazy solution of including everything at once.
I have no idea if you can generate this directly with xCode, anyway it's easy enough to do it by yourself as it's just a bunch of includes or imports.
The public header folder path is generally "MyLibraryOrFramework/Headers" (just look inside any Cocoa's framework for example).
And last, if you want something really reusable and seamless, I suggest you use frameworks instead of static library (which is nearly similar).
Look at this fine answer to understand why it fits perfectly what you need:
=> https://stackoverflow.com/a/6389802/1075192
VoilĂ , hope this answer helped a bit.

What does "import <XYZ/XYZ.h>" mean

I am new to objective-c and started iphone application development. I have noticed the import statement like import <UIKit/UIKit.h> etc... I wanted to know what does it mean. Why not simply import <UIKit> or import <UIKit.h>? In fact if I do that, it gives a no-such-file-error"!
So does it mean that we should name our files like that? So that when we import the header, it looks like MyApplication/MyApplication.h? Or is it just for the libraries? Even if it is, then why is that so?
This syntax looks weird to me, so I am just asking out of curiosity. But may be I am supposed to use them somewhere that I am not doing. I guess knowing is the best solution :)
UIKit/UIKit.h is a path. UIKit is some package and UIKit.h is the header that you are actually importing.
This is common for large frameworks and libraries in Objective-C, C, and C++.
This is just a convention for frameworks - the parent directory has the same name as the header file. You don't need to do this for headers which are not part of frameworks.