What is the motivation for querying __has_feature(objc_arc) - objective-c

I'm taking a look at some legacy code I need to maintain, and I see many spots where there is the following query:
#if __has_feature(objc_arc)
// ARC is On
// ...
#else
// ARC is Off
// ...
#endif
What could be the motivation for keeping the 'ARC is Off' code?

There is little motivation to keep the no-ARC code in .m files, because you can choose to always compile those with ARC enabled.
In a .h file, you need to keep the no-ARC code if the header file might be imported by a .m file that still uses manual reference counting and the maintainer of that .m file doesn't want to convert the .m file to ARC.

Related

Nested #import statements: how to hide nested ones?

I have the following project structure:
Main.h
Son1.h
Son2.h
They're not related (no father/son relationships), just two imports, like in Main.h I have:
#import Son1.h
#import Son2.h
If, from another file I write
#import Main.h
I will see all the methods/properties of Main.h (and that's ok) but I will also see the methods of Son1.h and Son2.h.
How can I prevent this?
It's important to understand what #import (and the C version: #include) do.
Compilation of C programs conceptually have 3 steps:
Preprocessing
Compiling
Linking
The directives beginning with # are acted on by the preprocessor (it doesn't matter at all whether this is a separate binary or part of the compiler). Both of these statements cause the contents of the named file to inserted into the importing (or including) file at the point where the directive is found. This is completely language-agnostic. The imported file can have anything in it. You can import a JPG, if you want (but good luck compiling!).
In your example, by importing Son1.h and Son2.h in Main.h, you are creating, from the compiler's perspective, a single file with the contents of Son1.h followed by the contents of Son2.h followed by whatever is in Main.h itself. At this level, the idea of hiding content doesn't make sense. You explicitly asked the preprocessor to put those contents there. It doesn't know anything about the text it's inserting, so it can't follow any kind of Objective-C directive, even if such existed.
The comments are getting to another point. Importing in a .h should be kept to an absolute minimum. The most common reasons to import are for class and protocol type definitions, and Objective-C allows you to forward declare both of these precisely to avoid otherwise necessary imports.
If you have something like:
#interface MyClass : NSObject
#property(nonatomic, strong) MyOtherClass *myOtherClass;
#end
You normally would have to #import "MyOtherClass.h". However, with forward declarations, you can do this instead:
#class MyOtherClass;
And move the #import to the implementation file, which is generally hidden from other files.

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?

Does Objective-C load the whole #imported file?

I'm trying to understand what really happens at compile time and runtime with imported files.
Does #import "file.h" directive essentially copy and paste the entire file.m into the current file? Or does it just specify that file's location and create the necessary attributes as they are instantiated?
The imports are handled by the preprocessor in C, C++, and Objective C, which creates one large file for the compiler. Every *.m, *.c, *.cpp file will each get all of the imports.
You can compile code on the command line with the -E flag to see the result after all the #imports are added.
Additionally, this question goes into some detail about #include vs #import, so it might give you more insight:
What is the difference between #import and #include in Objective-C?
As you can image, having lots of extra imports slows compilation. Jetbrain's AppCode has a feature that will optimize imports:
http://www.jetbrains.com/objc/features/
Does #import file.h statement essentially copy and paste the entire file.m into the current file?
It is not a statement, it is a preprocessor directive.
You're missing quotes or angle brackets around the file name.
#import "file.h" does indeed copy the whole file.h file in place of this directive into the current file. It doesn't, however, do anything with file.m.

Adding pre compiled headers in Xcode 4 Objective-C

This question is related to this:
Constants in Objective-C
I would like to add pre compiled headers to my project to store app constants. I want to this as an alternative to having a constants.h file and importing it wherever it's needed. Is my thinking correct here?
On the above thread a guy mentioned modifying "YourAppNameHere-Prefix.pch".. I'm not sure this is a good approach.
How exactly can I create my own *.pch file and add it to my Xcode project so I can store application level constants?
I have tried googling/searching here for this but I'm just getting Objective-C++ and Clang stuff.. I'm not sure this is relevant.
Cheers,
Conor
My answer probably not just in time, and especially for Xcode 6 but i hope i'll help other, who already want's to create it's own constant.h file and set it on all of project objects.
So
Create constant.h file by NSObject.
Put all of constants you need in .h file before #interface:
#import <...>
#define kSomeFirstConstant 1 //where 1 is an integer value
#define kSomeSecondConstant 2 //where 2 is an integer value
#interface Constant: NSObject
Create precompiled header file .pch (eg: precompiledFile.pch)
Put #import "constant.h" in .pch file right between #define and #endif:
#define ..._pch
#import "constant.h"
#endif
Configure prefix name and some other options in Project navigator, Building Settings of your project target:
Apple LLVM 6.0 Language
Increase sharing of Precompiled headers - NO
Precompile prefix header - YES
Prefix Header - TargetName/precompiledFile.pch (eg: MyTarget/precompiledFile.pch)
After that, run building process and all of your constant in constant.h file will be accessible in all of your project objects.
Also read this: http://qualitycoding.org/precompiled-headers/

Where to #import on Objective-C

My project has been increasing in size and I'm a little confused about where should I #import header files.
There are 3 main locations where I can import headers:
The .pch file (prefix)
The .h file (header)
the .m file (implementation)
I don't care if the compiler takes more time to compile the files, all I care is that the end product is as fast as possible and uses the least amount of memory.
So, my questions are:
If most files need a specific header, is it ok to add it to the .pch file, or is it more efficient to add it to just the required files?
Should imports be done in the .h or .m file? I know I must add it to the .h file if i'm going to declare it there, but if I don't need to declare it in the .h file is there a problem of leaving the import there?
No, it is not ok to include it into the .pch file. This file is precompiled to every module in the project. Read about it here.
Read this question and answer.
Put your imports in your .m whenever you can. If you are using a class in your .h use #class to forward the declaration, then #import in your .m. The only time you should import in your .h are protocols that you implement or superclasses.