What is the difference between #import and #include in Objective-C? - objective-c

What are the differences between #import and #include in Objective-C and are there times where you should use one over the other? Is one deprecated?
I was reading the following tutorial: http://www.otierney.net/objective-c.html#preamble and its paragraph about #import and #include seems to contradict itself or at least is unclear.

There seems to be a lot of confusion regarding the preprocessor.
What the compiler does when it sees a #include that it replaces that line with the contents of the included files, no questions asked.
So if you have a file a.h with this contents:
typedef int my_number;
and a file b.c with this content:
#include "a.h"
#include "a.h"
the file b.c will be translated by the preprocessor before compilation to
typedef int my_number;
typedef int my_number;
which will result in a compiler error, since the type my_number is defined twice. Even though the definition is the same this is not allowed by the C language.
Since a header often is used in more than one place include guards usually are used in C. This looks like this:
#ifndef _a_h_included_
#define _a_h_included_
typedef int my_number;
#endif
The file b.c still would have the whole contents of the header in it twice after being preprocessed. But the second instance would be ignored since the macro _a_h_included_ would already have been defined.
This works really well, but has two drawbacks. First of all the include guards have to be written, and the macro name has to be different in every header. And secondly the compiler has still to look for the header file and read it as often as it is included.
Objective-C has the #import preprocessor instruction (it also can be used for C and C++ code with some compilers and options). This does almost the same as #include, but it also notes internally which file has already been included. The #import line is only replaced by the contents of the named file for the first time it is encountered. Every time after that it is just ignored.

The #import directive was added to Objective-C as an improved version of #include. Whether or not it's improved, however, is still a matter of debate. #import ensures that a file is only ever included once so that you never have a problem with recursive includes. However, most decent header files protect themselves against this anyway, so it's not really that much of a benefit.
Basically, it's up to you to decide which you want to use. I tend to #import headers for Objective-C things (like class definitions and such) and #include standard C stuff that I need. For example, one of my source files might look like this:
#import <Foundation/Foundation.h>
#include <asl.h>
#include <mach/mach.h>

I agree with Jason.
I got caught out doing this:
#import <sys/time.h> // to use gettimeofday() function
#import <time.h> // to use time() function
For GNU gcc, it kept complaining that time() function was
not defined.
So then I changed #import to #include and all went ok.
Reason:
You #import <sys/time.h>:
<sys/time.h> includes only a part of <time.h> by using #defines
You #import <time.h>:
No go. Even though only part of <time.h> was already included, as
far as #import is concerned, that file is now already completely included.
Bottom line:
C/C++ headers traditionally includes parts of other include files.
So for C/C++ headers, use #include.
For objc/objc++ headers, use #import.

#include works just like the C #include.
#import keeps track of which headers have already been included and is ignored if a header is imported more than once in a compilation unit. This makes it unnecessary to use header guards.
The bottom line is just use #import in Objective-C and don't worry if your headers wind up importing something more than once.

I know this thread is old... but in "modern times".. there is a far superior "include strategy" via clang's #import modules - that is oft-overlooked..
Modules improve access to the API of software libraries by replacing the textual preprocessor inclusion model with a more robust, more efficient semantic model. From the user’s perspective, the code looks only slightly different, because one uses an import declaration rather than a #include preprocessor directive:
#import Darwin; // Like including all of /usr/include. #see /usr/include/module.map
or
#import Foundation; // Like #import <Foundation/Foundation.h>
#import ObjectiveC; // Like #import <objc/runtime.h>
However, this module import behaves quite differently from the corresponding #include: when the compiler sees the module import above, it loads a binary representation of the module and makes its API available to the application directly. Preprocessor definitions that precede the import declaration have no impact on the API provided... because the module itself was compiled as a separate, standalone module. Additionally, any linker flags required to use the module will automatically be provided when the module is imported. This semantic import model addresses many of the problems of the preprocessor inclusion model.
To enable modules, pass the command-line flag -fmodules aka CLANG_ENABLE_MODULES in Xcode- at compile time. As mentioned above.. this strategy obviates ANY and ALL LDFLAGS. As in, you can REMOVE any "OTHER_LDFLAGS" settings, as well as any "Linking" phases..
I find compile / launch times to "feel" much snappier (or possibly, there's just less of a lag while "linking"?).. and also, provides a great opportunity to purge the now extraneous Project-Prefix.pch file, and corresponding build settings, GCC_INCREASE_PRECOMPILED_HEADER_SHARING, GCC_PRECOMPILE_PREFIX_HEADER, and GCC_PREFIX_HEADER, etc.
Also, while not well-documented… You can create module.maps for your own frameworks and include them in the same convenient fashion. You can take a look at my ObjC-Clang-Modules github repo for some examples of how to implement such miracles.

If you are familiar with C++ and macros, then
#import "Class.h"
is similar to
{
#pragma once
#include "class.h"
}
which means that your Class will be loaded only once when your app runs.

IF you #include a file two times in .h files than compiler will give error.
But if you #import a file more than once compiler will ignore it.

#include it used to get "things" from another file to the one the #include is used in.
Ex:
in file: main.cpp
#include "otherfile.h"
// some stuff here using otherfile.h objects,
// functions or classes declared inside
Header guard is used on the top of each header file (*.h) to prevent including the same file more then once (if it happens you will get compile errors).
in file: otherfile.h
#ifndef OTHERFILE
#define OTHERFILE
// declare functions, classes or objects here
#endif
even if you put #include "otherfile.h" n time in your code, this inside it will not be redeclared.

In may case I had a global variable in one of my .h files that was causing the problem, and I solved it by adding extern in front of it.

#include vs #import preprocessor directives
History:
#include -> #import -> [Precompiled Headers .pch] -> [#import Module(ObjC);] -> [import Module(Swift)]
#import is a next generation of #include which solves double inclusion and recursive includes for current .h file. Just single copy of included .h body in the current file
#import == #include + guard
guard looks like
#ifndef <some_unique_name>
#define <some_unique_name>
<header_body>
#endif
#include guardWiki(macro guard, header guard, file guard) - prevents multi including a header by a preprocessor that can slow down a build time
#include and #import uses a kind of copy/paste mechanism - recursively copy .h file body(everything except #include, #import directives. It means that the result file will not contain #include, #import directives)
You can check result if select .m file Product -> Perform Action -> Preprocess ".m"
#include example
//A.h
#interface A : NSObject
- (int)startA;
#end
//ViewController.h
#include "A.h"
ViewController.m after preprocessing
#interface A : NSObject
- (int)startA;
#end
#interface ViewController : UIViewController
#end
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
}
#end
double inclusion example
//A.h
#interface A : NSObject //Build time error: Duplicate interface definition for class 'A'
#end
//B.h
#include "A.h"
//C.h
#include "A.h"
//#import "A.h" to solve
#include "B.h"
recursive includes example
//A.h
#include "B.h" //Build time error: #include nested too deeply
//#import "B.h" to fix it
#interface B : NSObject //Build time error: Duplicate interface definition for class 'A'
#end
//B.h
#include "A.h" //Build time error: #include nested too deeply
//#import "A.h" to fix it
#interface B : NSObject //Build time error: Duplicate interface definition for class 'B'
#end
[#import in .h or .m]

Related

Different C++ include statements throws errors in the Objective-C header

I'm trying to use OpenCV in Objective-C++ code which I will call from Swift. First I used this answer for connecting Objective-C and Swift. So after these manipulations I get three files:
Bridging-Header.h:
#import "opencvtest.h"
opencvtest.h:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#include <opencv2/core/core.hpp>
//#include <dlib/image_loader/load_image.h>
#interface CustomObject : NSObject
- (cv::Mat)cvMatFromUIImage:(UIImage *)image;
#end
opencvtest.mm:
#import "opencvtest.h"
Error:
/Users/user/Documents/XcodeProjects/Swift_HelloWorld/Swift_HelloWorld/Swift_HelloWorld-Bridging-Header.h:5:9: note: in file included from /Users/user/Documents/XcodeProjects/Swift_HelloWorld/Swift_HelloWorld/Swift_HelloWorld-Bridging-Header.h:5:
#import "opencvtest.h"
^ /Users/user/Documents/XcodeProjects/Swift_HelloWorld/Swift_HelloWorld/opencvtest.h:23:4: error: expected a type
- (cv::Mat)cvMatFromUIImage:(UIImage *)image; ^ <unknown>:0: error: failed to import bridging header '/Users/user/Documents/XcodeProjects/Swift_HelloWorld/Swift_HelloWorld/Swift_HelloWorld-Bridging-Header.h'
Also, if I add line #include <dlib/image_loader/load_image.h> in the opencvtest.h then I get:
/usr/local/include/DLIB/string/string.h:7:10: error: 'sstream' file not found
#include <sstream>
^
<unknown>:0: error: failed to import bridging header '/Users/user/Documents/XcodeProjects/Swift_HelloWorld/Swift_HelloWorld/Swift_HelloWorld-Bridging-Header.h'
I want to note that all these errors occurs only when I put these include statements in this header, when I used it in .mm file all works fine. But I need them in the header for declarations.
So, how can I fix it?
The interface of your Objective-C objects usable in Swift and thus visible in the bridging header cannot reference any C++ types. You need to write an Objective-C++ wrapper in such a way that C++ types are only mentioned in your .mm files and in headers used in the .mm files. You can hide the parts of the interface that use C++ by using extensions in Objective-C++ code. Please see the following question and questions referenced there for examples of how to do that:
objective C opencv wrapper for swift project does not see STL headers

Objective-c - Replace #import with #define

Is there a way to replace a class name #import through a #define macro? I want it to be made in all my project and not just in one file. So I don't want to make a #ifdef / #ifndef in each class that include the #import that I want to replace.
Something like... I have
#import "ClassSomething.h"
in 5 classes. I want to replace it with an
#import "ClassSomethingCustom.h"
but only
#ifdef SomethingIsDefined
First, Objective-C's compiler (gcc or clang) do a good job of not cluttering the compiled source with duplicated header information. There's nothing wrong with including both headers - unless the headers re-define the same class (which is what I suspect is the case here).
Replace #import "ClassSomething.h" in all your files with #import CLASS_SOMETHING_HEADER
Then, in your .pch file, have the following:
#ifdef SomethingIsDefined
#define CLASS_SOMETHING_HEADER "ClassSomethingCustom.h"
#else
#define CLASS_SOMETHING_HEADER "ClassSomething.h"
#endif
This isn't really ideal, though, as pre-processor macros that deal with imports can lead to many unforeseen errors. It's not a common pattern and future developers may not properly understand what you've done.
Another option you might want to consider is a pattern that is commonly used in libraries that support both iOS and OS X.
#ifdef SOME_IOS_IDENTIFIER_I_FORGOT_TO_LOOK_UP
typedef UIColor MyColor
#else
typedef NSColor MyColor
#endif
In this case you'd name your two classes differently and use an alias to reference them in your source. Place the relevant imports in a "parent" header file like "MyProjectImports.h" or something. (where you'd import AppKit or UIKit)
Alternatively, you might want to consider using a Category on ClassSomething (i.e. "ClassSomething+Custom.h") to include the custom functionality you need. This will likely require some re-working of the logic underlying the two different classes, but in the files that need just the custom behavior, can conditionally #import the Category header and the other files can be left alone.
Without more knowledge on exactly how these two classes differ or will be used, I can't help you much further.
HtH
Put this into a header file:
#ifdef SomethingIsDefined
#import "ClassSomethingCustom.h"
#else
#import "ClassSomething.h"
#endif
and include this header file in you 5 classes.
You can change the content ClassSomething.h and put the #ifdef SomethingIsDefined only in there.
Perhaps what you need is to paste the code #dasdom wrote into your .pch file (pre-compiled header) file instead of every header. With that, you only need to paste it once and all the files will add this header automatically
#ifdef SomethingIsDefined
#import "ClassSomethingCustom.h"
#else
#import "ClassSomething.h"
#endif
I hope this helps you. Otherwise, please can you explain it deeply?

How to determine if modules are supported in Xcode?

When I enable the -Weverything custom compiler flag and modules are supported in Xcode, it tells me to switch to using modules - so I change this type of thing:
#import <Foundation/Foundation.h>
to this:
#import Foundation;
...and everything is fine until someone later imports one of my classes into their legacy projects that do not have modules enabled, at which point they have to revert the #import to a #import.
My question is this: Is it possible to wrap these in some sort of preprocessor macro to pick out the correct one at compile time?
Example of what I'm hoping for:
#ifdef MODULES_SUPPORTED
#import Foundation;
#else
#import <Foundation/Foundation.h>
#endif
Thanks
Jase
This is an old question, but needed to know how to do this too. Here is a way to do it:
#ifdef __has_feature(modules)
#import Foundation;
#else
#import <Foundation/Foundation.h>
#endif
Reference: CLANG LANGUAGE EXTENSIONS

How to put macros and constants into .pch file in an iOS project?

I heard that the .pch is good for putting macros and constants definitions, so for its default content:
#import <Availability.h>
#ifndef __IPHONE_4_0
#warning "This project uses features only available in iOS SDK 4.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
where should the definitions be put in? It is strange that it seems to be importing UIKit.h, but ViewController.h also import that same file (I thought the .pch is imported by all files by default? So ViewController.hshouldn't need to import UIKit.h again)
Precompiled headers are meant to improve overall compile times for projects, so the design of precompiled headers is entirely driven by performance concerns.
The use case for precompiled headers is relatively simple: when there is a common set of headers that is included in nearly every source file in the project, we precompile that bundle of headers into a single precompiled header (PCH file).
The .pch file allows you to import files like UIKit.h and Foundation.h(rather than importing them in every .h of your project) If you have those files imported in the .pch, in your own classes don't need to import them.
The significance of #ifdef OBJC is so that you don't import headers containing objective-c code if you don't have the compiler set to build objective c code (hence avoiding lots of compiler errors).
Any extra imports I usually put in with:
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif
You are correct, there is no need to import one of those again, but there is no harm in doing so.

What is #ifdef __OBJC__ doing and why libraries listed below?

I believe the #ifdef __OBJC__ directive is ensuring that I import the following class libraries for Objective-C only. What is the purpose of listing the class libraries after the ifdef statement? Doesn't this code example kinda defeat the purpose?
#ifdef __OBJC__
#import <foundation/foundation.h>
#import <uikit/uikit.h>
#import <coredata/coredata.h>
#endif
</coredata/coredata.h></uikit/uikit.h></foundation/foundation.h>
Objective-C is a superset of C (just like C++ is) and fairly often files from the different languages will be used in the same project and share headers, especially the prefix header. The #ifdef __OBJC__, like #ifdef __cplusplus, lets you include (or #import for Objective-C) headers for only the appropriate language.
The same header included in .c, .cpp, and .m files (with default compiler settings) would only have __OBJ__ defined for the .m files.
Basically in that code if you are using Objective C it will import those 3 libraries
#import <foundation/foundation.h>
#import <uikit/uikit.h>
#import <coredata/coredata.h>
The purpose of that if, is to not import them unless it is necessary.
They are listed after the #endif just as a reminder, so it makes the code easier to read. Otherwise you'd have to look up above to see what the #endif was ending.
The reason this is done is so that this code can still be compatible with regular C code that may want to use the functionality in that C file (at least that's what it looks like to me). By including those libraries only when OBJC is defined it ensures that the libraries are ONLY imported when you are compiling for objective c and not for standard C.