Why do we use -fobjc-arc instead of removing code with #define?

  • I'm curious as to why, when using non-ARC code, the recommendation is to "opt out" the file with -fobjc-arc.

    How about doing something like this…

    #ifndef HEY_ARC_IS_IN_USE
        [foo retain] ;
    #endif

    This way the file is fixed "once and for all", and I don't have to be setting -fobjc-arc every time I reuse this file from now until kingdom come.  Certainly -fobjc-arc is also useful, but the #define seems to make much more sense for, say, my personal reusable class and class extension files which tend to be quite short.  They contain only a few -retain, -release, etc.

    Does Apple even provide the required HEY_ARC_IS_IN_USE definition?  I can't find any such thing.

    Jerry Krinock
  • Yep, you can do this.  The #if you're looking for is:

    #if __has_feature(objc_arc)

    ...

    #endif

    You can just scatter that everywhere in code, or you could do something like this:

    #if __has_feature(objc_arc)

    #define DD_RETAIN(_o) (_o)
    #define DD_RELEASE(_o)
    #define DD_AUTORELEASE(_o) (_o)

    #else

    #define DD_RETAIN(_o) [(_o) retain]
    #define DD_RELEASE(_o) [(_o) release]
    #define DD_AUTORELEASE(_o) [(_o) autorelease]

    #endif

    This way you can just do this, and not have to worry about whether ARC is on or not:

    foo = DD_RETAIN(bar);

    Cheers,

    Dave

    On Jun 23, 2012, at 6:37 PM, Jerry Krinock wrote:

    > I'm curious as to why, when using non-ARC code, the recommendation is to "opt out" the file with -fobjc-arc.
    >
    > How about doing something like this…
    >
    > #ifndef HEY_ARC_IS_IN_USE
    > [foo retain] ;
    > #endif
    >
    > This way the file is fixed "once and for all", and I don't have to be setting -fobjc-arc every time I reuse this file from now until kingdom come.  Certainly -fobjc-arc is also useful, but the #define seems to make much more sense for, say, my personal reusable class and class extension files which tend to be quite short.  They contain only a few -retain, -release, etc.
    >
    > Does Apple even provide the required HEY_ARC_IS_IN_USE definition?  I can't find any such thing.
    >
    > Jerry Krinock
  • On 2012 Jun 23, at 18:41, Dave DeLong wrote:

    > Yep, you can do this…

    Very good, Dave.  I'm doing it.

    But now I wonder why Apple did not do this, as they did with Garbage Collection.  Methods -retain, -release, and -autorelease are no-ops when GC is on.

    Why didn't Apple do the same thing for ARC?
  • On 24/06/2012, at 1:55 PM, Jerry Krinock wrote:

    > Why didn't Apple do the same thing for ARC?

    Because ARC is a compiler technology that inserts -retain, -release automatically and silently into your code as it is compiled. The methods have to be there in order for memory management to work at runtime - ARC doesn't do anything at runtime, by then your code is exactly the same as if you'd written memory management manually (though hopefully without any mistakes!).

    --Graham
  • On Jun 24, 2012, at 12:25 PM, Graham Cox wrote:

    >
    > On 24/06/2012, at 1:55 PM, Jerry Krinock wrote:
    >
    >> Why didn't Apple do the same thing for ARC?
    >
    >
    > Because ARC is a compiler technology that inserts -retain, -release automatically and silently into your code as it is compiled. The methods have to be there in order for memory management to work at runtime - ARC doesn't do anything at runtime, by then your code is exactly the same as if you'd written memory management manually (though hopefully without any mistakes!).
    >
    > --Graham
    >

    They could still #define them at compile time to be nothing and then insert the code to call the underlying functions just as they do now, that inserts objc_release() and other calls directly into the compiled code anyway. There's no incompatibility there. My guess is that Apple wanted to move totally away from manual retain/release and have people not even see it, so instead of #defining out the calls, they wrote the conversion tool which removes them entirely, and does a few other things too, a clean-break approach.
  • Le 24 juin 2012 à 07:18, Roland King a écrit :

    >
    > On Jun 24, 2012, at 12:25 PM, Graham Cox wrote:
    >
    >>
    >> On 24/06/2012, at 1:55 PM, Jerry Krinock wrote:
    >>
    >>> Why didn't Apple do the same thing for ARC?
    >>
    >>
    >> Because ARC is a compiler technology that inserts -retain, -release automatically and silently into your code as it is compiled. The methods have to be there in order for memory management to work at runtime - ARC doesn't do anything at runtime, by then your code is exactly the same as if you'd written memory management manually (though hopefully without any mistakes!).
    >>
    >> --Graham
    >>
    >
    > They could still #define them at compile time to be nothing and then insert the code to call the underlying functions just as they do now, that inserts objc_release() and other calls directly into the compiled code anyway. There's no incompatibility there. My guess is that Apple wanted to move totally away from manual retain/release and have people not even see it, so instead of #defining out the calls, they wrote the conversion tool which removes them entirely, and does a few other things too, a clean-break approach.

    The less the compiler has too make assumption, the better.
    Converting code from manual ref counting to ARC is mostly doable automatically, but not always. So, instead of trying to do it each time you compile a file, Apple force you to do it once and for all (using the ARC migration assistant), and then don't have to include all the migration logic in the compiler.

    -- Jean-Daniel
  • On 24.06.2012, at 03:41, Dave DeLong wrote:
    > #define DD_RETAIN(_o) (_o)
    > #define DD_RELEASE(_o)
    > #define DD_AUTORELEASE(_o) (_o)

    IIRC GNUstep already has standard-defined RETAIN() macros etc. (When they added their garbage collector, way before Apple made their attempt at one) Might be worth just keeping the same terminology.

    Cheers,
    -- Uli Kusterer
    "Die Zeugen des TeachText sind überall..."
    http://www.wiederholungstaeter-podcast.de
  • On 24.06.2012, at 05:55, Jerry Krinock wrote:
    > Why didn't Apple do the same thing for ARC?

    Because the whole point of ARC is that you don't have to write retain/release calls, and thus can't make mistakes in them. Since, once compiled, ARC code is pretty much identical to manually managed code (and you can mix and match ARC and manually managed modules), there really is no point in using ARC if you're then going to add manual calls anyway. That would only cause your code to exist in two versions (ARC and non-ARC) with two different sets of possible memory management bugs. So not only are you STILL writing manual-managed code, you've now also DOUBLED your QA load.

    Cheers,
    -- Uli Kusterer
    "The Witnesses of TeachText are everywhere..."
    http://www.masters-of-the-void.com
  • On Jun 23, 2012, at 8:55 PM, Jerry Krinock <jerry...> wrote:
    > But now I wonder why Apple did not do this, as they did with Garbage Collection.  Methods -retain, -release, and -autorelease are no-ops when GC is on.
    >
    > Why didn't Apple do the same thing for ARC?

    Objective-C garbage collection supported a hybrid mode, where the same binary could run with or without GC enabled. Such code was written with retain/release calls in place, but those calls were ignored if you were running with GC on. This hybrid mode was used in system libraries and other code that needed to run in both GC and non-GC apps.

    The problem with hybrid mode is that it is difficult to keep both modes functioning. If you have retain/release statements that are ignored, and you are not truly fanatical about testing both modes, then in short order you will find that your retain/release statements are incorrect because of subsequent code changes.

    ARC has no need for GC's hybrid mode, because ARC code and non-ARC code are fully interoperable. We recommend each file be written for either one or the other, with no attempt to be ARC-agnostic.

    --
    Greg Parker    <gparker...>    Runtime Wrangler
  • On 26/06/2012, at 7:42 AM, Greg Parker wrote:

    > We recommend each file be written for either one or the other, with no attempt to be ARC-agnostic.

    Does this imply that ARC can be adopted gradually?

    For example, I have a large project that uses manual memory management. If I add a new class to it, can I write that class with ARC without having to adopt it for the whole project? I've been able to do that with properties and other Obj-C 2.0 stuff very successfully, but it wasn't clear that ARC could be managed the same way. If it can be done, how is ARC enabled for a specific class?

    --Graham
  • Yes, you can do this, because ARC is a compile-time option and files are compiled individually.

    To compile with ARC, you'll need to use the -fobjc-arc flag.

    Cheers,

    Dave

    Sent from Jane

    On Jun 25, 2012, at 6:20 PM, Graham Cox <graham.cox...> wrote:

    >
    > On 26/06/2012, at 7:42 AM, Greg Parker wrote:
    >
    >> We recommend each file be written for either one or the other, with no attempt to be ARC-agnostic.
    >
    >
    > Does this imply that ARC can be adopted gradually?
    >
    > For example, I have a large project that uses manual memory management. If I add a new class to it, can I write that class with ARC without having to adopt it for the whole project? I've been able to do that with properties and other Obj-C 2.0 stuff very successfully, but it wasn't clear that ARC could be managed the same way. If it can be done, how is ARC enabled for a specific class?
    >
    >
    > --Graham
  • On 26.06.2012, at 03:20, Graham Cox wrote:
    > On 26/06/2012, at 7:42 AM, Greg Parker wrote:
    >> We recommend each file be written for either one or the other, with no attempt to be ARC-agnostic.
    >
    > Does this imply that ARC can be adopted gradually?

    Yes. ARC (effectively) generates the release/retain statements for you, so as long as none of your headers in some way expose code that might be ARC or non-ARC, and you follow the naming conventions, you can turn ARC on/off per compilation unit (i.e. "source file").

    > For example, I have a large project that uses manual memory management. If I add a new class to it, can I write that class with ARC without having to adopt it for the whole project? I've been able to do that with properties and other Obj-C 2.0 stuff very successfully, but it wasn't clear that ARC could be managed the same way. If it can be done, how is ARC enabled for a specific class?

    Haven't yet had to use it, but Stack Overflow (http://stackoverflow.com/questions/8768176/how-to-add-arc-for-specific-file) says the flag is logically named "-fobjc-arc". Just specify that for a source file.

    Cheers,
    -- Uli Kusterer
    "The Witnesses of TeachText are everywhere..."
  • Le 26 juin 2012 à 11:24, Uli Kusterer a écrit :

    > On 26.06.2012, at 03:20, Graham Cox wrote:
    >> On 26/06/2012, at 7:42 AM, Greg Parker wrote:
    >>> We recommend each file be written for either one or the other, with no attempt to be ARC-agnostic.
    >>
    >> Does this imply that ARC can be adopted gradually?
    >
    > Yes. ARC (effectively) generates the release/retain statements for you, so as long as none of your headers in some way expose code that might be ARC or non-ARC, and you follow the naming conventions, you can turn ARC on/off per compilation unit (i.e. "source file").
    >
    >> For example, I have a large project that uses manual memory management. If I add a new class to it, can I write that class with ARC without having to adopt it for the whole project? I've been able to do that with properties and other Obj-C 2.0 stuff very successfully, but it wasn't clear that ARC could be managed the same way. If it can be done, how is ARC enabled for a specific class?
    >
    >
    > Haven't yet had to use it, but Stack Overflow (http://stackoverflow.com/questions/8768176/how-to-add-arc-for-specific-file) says the flag is logically named "-fobjc-arc". Just specify that for a source file.
    >

    You may have to pass this flag to the linker too, at least if you target 10.6, to let the linker know it has to link using the ARC runtime library.

    > Cheers,
    > -- Uli Kusterer
    > "The Witnesses of TeachText are everywhere..."

    -- Jean-Daniel
previous month june 2012 next month
MTWTFSS
        1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30  
Go to today