Skip to content

Instantly share code, notes, and snippets.

@HIRANO-Satoshi
Last active May 12, 2018 19:07
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save HIRANO-Satoshi/2823399 to your computer and use it in GitHub Desktop.
Save HIRANO-Satoshi/2823399 to your computer and use it in GitHub Desktop.
ARCMacro.h: Enables compilation both in ARC and non-ARC
/*
* ARCMacro.h 1.2 2016/10/30 https://gist.github.com/2823399 Thanks: @olance
* ARCMacro.h 1.1 2012/05/29 https://gist.github.com/2823399
*
* ARCMacro.h realizes coexistence of both the ARC (Automatic
* Reference Counting) mode and the Non-ARC mode of Objective-C
* in the same source code. This macro works for iOS and Mac OS X.
*
* This is a by-product of joint research by AIST and The University of Ryukyu.
* HIRANO Satoshi (AIST), NAKAMURA Morikazu (U. Ryukyu) and GUAN Senlin (U. Ryukyu)
*
* Author: HIRANO Satoshi (AIST, Japan) on 2011/11/14
* Copyright 2011-2012 National Institute of Advanced Industrial Science
* and Technology (AIST), Japan. Apache License 2.0.
*
* Usage:
* #import "ARCMacro.h"
* [o1 RETAIN];
* o2 = [[o3 RETAIN] AUTORELEASE];
* [super DEALLOC];
*/
#if __clang__
#if __has_feature(objc_arc)
#define S_RETAIN self
#define S_AUTORELEASE self
#define S_RELEASE self
#define S_DEALLOC self
#else
#define S_RETAIN retain
#define S_AUTORELEASE autorelease
#define S_RELEASE release
#define S_DEALLOC dealloc
#endif
#else
#define S_RETAIN retain
#define S_AUTORELEASE autorelease
#define S_RELEASE release
#define S_DEALLOC dealloc
#endif
@HIRANO-Satoshi
Copy link
Author

ARCMacro.h: Simple macros which enable compilation both in ARC mode and non-ARC mode for iOS and Mac OS X

Summary

ARCMacro.h realizes compilation of Objective-C source files both in Automatic Reference Counting (ARC) compilation mode and Manual Reference Counting (MRC, non-ARC) compilation mode without changing the compiler switch. This is useful when you provide a library in the source code form for ARC apps and MRC apps. And your code can take advantage of the ARC mode that is much safer.

Example:

The following example can be compiled in both ARC and MRC compilation modes.

#import "ARCMacro.h"
...

- (void) method:(Name *)aName {
    Person *person = [[Person alloc] init];
    [userManager addPerson:person];
    [person RELEASE];

    Group *group = [[[Group alloc] init] AUTORELEASE];
    [group method2];

    ivar = [aName RETAIN];

    @autoreleasepool {
         // code
    }
}

- (void) dealloc {
    [ivar RELEASE], ivar = nil;
    [super DEALLOC];
}

Supported Platforms

ARCMacro.h works for Xcode 4.2 or higher and any version of iOS and Mac OS X.

Usage

Step 0

Read "Transitioning to ARC Release Notes".

http://developer.apple.com/library/mac/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html

ARC is supported in Mac OS X v10.6 and higher (64-bit applications) and in iOS 4 and higher, while MRC is supported in any version of iOS and Mac OS X. Weak references are not supported in iOS 4.x and Mac OS X 10.6.

Step 1

Download ARCMacro.h and add #import.

#import "ARCMacro.h"

Step 2

Replace MRC methods with corresponding ARC macros. Replace existing "retain" with "RETAIN", "release" with "RELEASE", "autorelease" with "AUTORELEASE", and [super dealloc] with [super DEALLOC].

retainCount is not supported.

Note that GNUStep and SenTesting have their own RETAIN/RELEASE definitions and SenTesting is included in the iOS SDK. Import ARCMacro.h after SenTestingKit.h if you use SenTesting, though SenTestingUtilities.h says RETAIN in SenTesting was deprecated and should not be used. In case you experience contention, edit ARCMacro.h to change to your favorite name.

Step 3

Add qualifiers for ARC. The qualifiers are __block, __unsafe_unretained, __bridge, __bridge_transfer, __strong, __autoreleasing, unsafe_unretained, and strong. Since the compiler silently ignores the qualifiers during MRC compilation, you can add them as described in "Transitioning to ARC Release Notes". Use enough time for looking for object cycles and cut them by adding __weak or __unsafe_unretained.

Example:

id __unsafe_unretained delegate;

iOS 4.x and Mac OS X 10.6 does not support weak references. If you use __weak or weak in your code and it is compiled with iOS Deployment Target 4.x or Mac OS X 10.6, the compiler complains and fails. They are not allowed in MRC compilation mode, too. Thus, if you want to support iOS 4 or Mac OS X 10.6, use __unsafe_unretained and unsafe_unretained rather than __weak and weak.

__unsafe_unretained means just assign without retain. If you want to avoid dangling references, assign nil after you finish using __unsafe_unretained references.

We don't provide conversion from __weak to __unsafe_unretained, since they have different meanings.

Step 4

Replace NSAutoreleasePool block to @autoreleasepool block. @autoreleasepool works in MRC mode.

Take care of other staff described in "Transitioning to ARC Release Notes".

Step 5

Once you finish the above change, your code is compatible both with ARC compilation and MRC compilation (with -fno-objc-arc). Your code adapts itself to both compilation modes without compiler switch.

Note

Don't forget enough test for the both compilation modes.

History

See also

Copyright and License

This is a by-product of joint research by AIST and The University of Ryukyu.

HIRANO Satoshi (AIST), NAKAMURA Morikazu (U. Ryukyu) and GUAN Senlin (U. Ryukyu).

Author: HIRANO Satoshi

Copyright 2011-2012 National Institute of Advanced Industrial Science and Technology (AIST), Japan

Apache License 2.0

@olance
Copy link

olance commented Jan 9, 2015

ARCMacro.h works for Xcode 4.2 or higher and any version of iOS and Mac OS X

Xcode 4.2 up to 4.6 had support for GCC 4.2 and LLVM GCC 4.2. These macros do not work with these versions of GCC, has __has_feature is not supported in GCC.

The following should fix the issue:

#if __clang__
    #if __has_feature(objc_arc)
        #define S_RETAIN self
        #define S_AUTORELEASE self
        #define S_RELEASE self
        #define S_DEALLOC self
    #else
        #define S_RETAIN retain
        #define S_AUTORELEASE autorelease
        #define S_RELEASE release
        #define S_DEALLOC dealloc
    #endif
#else
    #define S_RETAIN retain
    #define S_AUTORELEASE autorelease
    #define S_RELEASE release
    #define S_DEALLOC dealloc
#endif

This is satisfactory as ARC is indeed not supported when compiling with GCC/LLVM GCC.

@HIRANO-Satoshi
Copy link
Author

merged. Thanks, @olance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment