'__bridge' casts have no effect when not using ARC - objective-c

When compiling an older project in Xcode 4.5, there is a warning:
'__bridge' casts have no effect when not using ARC
What's the proper way to get rid of this warning, such that the code works well in both ARC and non-ARC projects?

Any individual source file has to either be compiled with ARC or not compiled with ARC. You should just make up your mind which it is and always use that method for the particular source file. Provided you stick to the memory management naming conventions, you can mix ARC and non ARC source files in the same project.
The reason I say the above, is that if you have code that was written for ARC and you compile it without ARC, there will be memory leaks and premature deallocations all over the place thanks to the fact that all of the retains, releases and autoreleases are missing.

With a few #define's it is quite possible to write source files which compile correctly for more than one of MRC, ARC & GC.
Xcode does not allow you to enable both ARC & GC, knowing that we can write:
#if defined(__OBJC_GC__)
# define USING_GC 1
#else
# define USING_GC 0
#endif
#if __has_feature(objc_arc)
# define USING_ARC 1
#else
# define USING_ARC 0
#endif
#if USING_ARC || USING_GC
# define USING_MRC 0
#else
# define USING_MRC 1
#endif
which will define just one of USING_GC, USING_MRC and USING_ARC as 1 and the other two as 0. You can put that in your projects prefix header (.pch).
You can use these defines directly in your code to include/exclude things like bridge casts; or better to define macros for memory calls, casting, etc. which expand to the appropriate code based on the memory model in use.
HTH

Simply turn on ARC for that file:
-fobjc-arc
(Go to Build Phases > Compile Sources > Compiler Flags)

Related

Writing library code to support both ARC and MRR

I'm working on a library and I would like to support both memory management approaches (ARC and MRR) in one codebase.
I don't want to force users to use special flags for my code (-fobjc-arc).
I know about the preprocessor test: #if __has_feature(objc_arc), but what is the best practice to use that to cover the all differences?
Does anyone have any experience with that to make it clean and easy to work with?
The preferable way would be to use some macros for translations between ARC and non-ARC, which I can use in my code.
=========
My problem was solved by the accepted answer, but as a tip for others, I found a blog post by John Blanco giving the best set of examples for how to handle my problem.
Refer the code of MBProgressHUD in github. I think, that's what you want.
#if __has_feature(objc_arc)
#define MB_AUTORELEASE(exp) exp
#define MB_RELEASE(exp) exp
#define MB_RETAIN(exp) exp
#else
#define MB_AUTORELEASE(exp) [exp autorelease]
#define MB_RELEASE(exp) [exp release]
#define MB_RETAIN(exp) [exp retain]
#endif
This is how they are using these macros
self.indicator = MB_AUTORELEASE([[MBRoundProgressView alloc] init]);
Either use ARC and instruct people who will use the code to set compilation flags per file (-fobjc-arc), and force them to do so by adding this to the header:
#if !__has_feature(objc_arc)
#error ARC must be enabled!
#endif
Or build as lib/framework with ARC enabled. Wrapping memory management code in preprocessor directives is a terrible idea.
One way to support both ARC and Non-ARC code is to go to the Target, Build Phases, and to the Compile Sources section.
From there you should see all your .m files. You can then add to any file -fno-objc-arc under the Compiler Flags to tell the compiler to ignore ARC.
Yeah, don't do this. You'll end up having to test your code fully twice for every change. And debugging everything twice. It isn't worth the effort.
You really really want to write your code purely ARC or purely non-ARC.
There are very few constructs that can appear in a header file that won't work in one or the other.

Library in Objective C for OSX

I'm creating a library for plotting a particular graph. How do I make it work in both ARC and MRC environment?
Compiled MRC/ARC code can be called from ARC/MRC code - ARC is essentially a compile-time technology which automatically inserts calls to the reference-counting memory management routines. At runtime ARC & MRC code interoperates without issue.
Therefore if you intend to ship your library in compiled form you can write it using either MRC or ARC and it can be used by both ARC & MRC projects.
If you intend to ship your library in source form then you can [was "must", see edit below] write it using MRC. Users can then incorporate your library code directly into MRC projects.
To include it in ARC projects users add the source as usual and then for each source file the file must be marked as using MRC. This is done by selecting the file in the Compiler Sources section of the Build Phases tab of the Project settings and adding the flag -fno-objc-arc. The flag instructs the compiler to compile that particular source file as MRC.
Edit
The above was over strong, in general with ARC being newer than MRC then requirement is to include MRC source in ARC projects, and this is done by flagging the individual MRC files with -fno-objc-arc. However the reverse is equally supported, you can include ARC source in an MRC project by flagging the individual ARC files with -fobjc-arc.
In other words, Xcode has a project-wide setting, "Objective-C Automatic Reference Counting" found in the "Build Settings" pane of the project settings, which sets whether the project is MRC/ARC; and this setting can be reversed for individual source files, in the "Compile Sources" section of the "Build Phases" pane of project settings.
The simplest choice is to distribute your library in binary (compiled) form, as this avoids the user setting any flags.
You can define preprocessor macros for memory management calls that do nothing in ARC, and call the appropriate methods in MRC:
#if __has_feature(objc_arc)
# define ANRelease(obj)
# define ANAutorelease(obj) (obj)
# define ANRetain(obj) (obj)
#else
# define ANRelease(obj) [(obj) release]
# define ANAutorelease(obj) [(obj) autorelease]
# define ANRetain(obj) [(obj) retain]
#endif
You can't.
If you choose to use ARC (advisable) you have a set of restrictions (for instance you cannot manually call any memory management method) that you can bypass only turning it off, which is not really an option because you would end up with memory leaks all over the codebase.
A reasonable way to go is to have two different versions, one with MRC and one with ARC, but it seems like an unnecessary effort.
Your users can import your ARC-based library into a non-ARC project by using the -fobjc-arc compiler flag.

In Objective-C, is there a RELEASE definition besides DEBUG?

Is there a RELEASE defined or maybe it is by another name?
I kind of not want to use
#ifndef DEBUG
#endif
because the n may be less obvious than if we use a RELEASE, which is quite clear.
If none is available, then is adding the following to Support Files/project_name.pch a good way to have RELEASE defined?
#ifndef DEBUG
#define RELEASE 1
#endif
DEBUG is just defined in Xcode's Build Settings under Preprocessor Macros. In that section you can specify macros to be defined for all builds, debug builds or release builds. Just add RELEASE to the release section and you have what you want; or if you prefer #if over #ifdef put DEBUG=1, RELEASE=0 into the debug section and DEBUG=0, RELEASE=1 into the release section.
(And if you're not using Xcode your build system/compiler should have similar facilities.)

Run time check of ARC (Automatic Reference Counting)

How can I check if my program is running in an ARC (Automatic Reference Counting) device?
I can use this code:
#if ! __has_feature(objc_arc)
# define FMDBRelease(__v) ([__v release]);
#else
# define FMDBRelease(__v)
#endif
But this work in compile time. A easy code for this is:
if ([object respondsToSelector:#selector(release)]) {
[object release];
}
But not work. I am not finding it in any place. There are a solution for this?
ARC is a compile time technology, thus the #if __has_feature(objc_arc) way is the correct way of doing this.
You can't. ARC is a compile-time tool. It has no real presence at runtime, except for the insertion of calls that allow for tail-call optimization.

Pragma to explicitly enable ARC?

Is there a #pragma (or otherwise some construct) to explicitly enable automatic reference counting (ARC) in an Objective-C (or Objective-C++) source file? Even better if the source file can cause compilation to fail if ARC is not enabled.
I'm starting to have a number of ARC-only source files that can be potentially shared with other projects. Most of these contain category methods to extend built-in classes. I just don't want to accidentally include these in a non-ARC project and starts leaking out memory.
Thanks in advance!
As far as I can tell there is no way to explicitly enable or disable ARC.
However it is possible to detect if it is enabled. Simply add the following snippet to any file that requires ARC.
#ifndef __has_feature
#define __has_feature(x) 0 /* for non-clang compilers */
#endif
#if !__has_feature(objc_arc)
#error ARC must be enabled!
#endif
More info:
http://clang.llvm.org/docs/AutomaticReferenceCounting.html
http://clang.llvm.org/docs/LanguageExtensions.html#__has_feature_extension