Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

What is ARC?

edited August 2012 in Beta Posts: 2,161

No idea what "Automatic Reference Counting" is or what I should be looking out for in testing it. Can anyone enlighten me?

Comments

  • SimeonSimeon Admin Mod
    edited August 2012 Posts: 5,362

    (Edit: this is probably a better explanation: http://blog.mugunthkumar.com/articles/migrating-your-code-to-objective-c-arc)

    Apple introduced ARC technology as part of their Apple LLVM compiler.

    Objective-C uses a "reference counting" system to manage memory. (Lua uses "garbage collection" for comparison).

    Reference counting simply means that each object instance increases an internal counter each time it is used ("retained"). And decreases each time it is freed ("released"). When the counter reaches zero, it is supposed to mean that your code is no longer using the object anywhere and it can safely be deallocated. The memory can then be re-used for other objects.

    So over time Objective-C has developed a coding style entirely around its memory management system. Methods adopt special naming prefixes depending on what they do, memory-wise.

    So in classic Objective-C you might have this code:

    //Interface
    @interface MyObject : NSObject
    
    //A "retain" property implies ownership, 
    //  i.e. any object assigned to this property will be retained
    @property (nonatomic, retain) NSArray* arrayOfObjects;
    
    - (void) methodOnMyObject:(NSObject*)anotherObject;
    
    @end
    
    //--------------------------
    //Implementation
    
    @implementation MyObject
    
    //Generates getter/setter code for this property
    @synthesize arrayOfObjects;
    
    - (id) init
    {
        self = [super init];
        if( self )
        {
            //Here we alloc a new array (reference count 1), 
            //  assign it to a "retain" property (reference count 2),
            //  add it to the global "autorelease" pool (reference count will be decreased to 1 in 
            //    the next iteration of the run loop — some point in the future)
    
            self.arrayOfObjects = [[[NSArray alloc] init] autorelease];
        }
        return self;
    } 
    
    - (void) dealloc
    {
        //Called when reference count for "MyObject" reaches zero
    
        //Release the array that we own
        //This causes every object inside the array to be "released" once, decrementing its
        // reference count and potentially deallocing
        [arrayOfObjects release];
    
        //Call superclass dealloc
        [super dealloc];
    }
    
    - (void) methodOnMyObject:(NSObject*)anotherObject
    {
        //Here we add a new object to our array
    
        //newObject is alloc'd, reference count is 1
        NSObject *newObject = [[NSObject alloc] init];
    
        //newObject is added to array, reference count increments to 2
        [arrayOfObjects addObject:newObject];
    
        //we must release "newObject" balancing out the initial alloc
        [newObject release];
    
        //We can do stuff with "anotherObject" but we should never "release" it, as 
        // we do not own the object
    }
    
    @end
    

    With ARC, the compiler inserts the "retain" and "release" calls for you (and optimises their placement and use). The above code becomes:

    //Interface
    @interface MyObject : NSObject
    
    //A "strong" property implies ownership
    @property (nonatomic, strong) NSArray* arrayOfObjects;
    
    - (void) methodOnMyObject:(NSObject*)anotherObject
    
    @end
    
    //--------------------------
    //Implementation
    
    @implementation MyObject
    
    @synthesize arrayOfObjects;
    
    - (id) init
    {
        self = [super init];
        if( self )
        {
            //LLVM does semantic analysis here and figures out how to balance the memory
            // it uses our "strong" ownership, and the fact we are allocing to work it out
    
            self.arrayOfObjects = [[NSArray alloc] init];
        }
        return self;
    } 
    
    //No need for a "dealloc" method. LLVM will write it.
    
    - (void) methodOnMyObject:(NSObject*)anotherObject
    {
        //Here we add a new object to our array
    
        //newObject is alloc'd, reference count is 1
        NSObject *newObject = [[NSObject alloc] init];
    
        //newObject is added to array, reference count increments to 2
        [arrayOfObjects addObject:newObject];
    
        //LLVM will release "newObject" here
    
        //We can do stuff with "anotherObject" but we should never "release" it, as 
        // we do not own the object
    }
    
    @end
    

    So it formalises the coding style and memory management in Objective-C. It's an extremely good addition, and I don't want to code without it anymore (it saves huge amounts of mechanical memory management code from being written).

    However migrating a large project, such as Codea, is filled with special cases. Such as "weak" properties, retain cycles, delegates and other memory use-cases that need to be reasoned about in order to apply ARC correctly. Sometimes I need to get involved with the conversion.

  • Posts: 2,161

    Ah. Now I know.

    *my brain hurts*

  • Posts: 1,255

    Once again, I'm reminded why I'm not coding in objective C.

  • SimeonSimeon Admin Mod
    Posts: 5,362

    It's not too bad, I like it a lot more than C++.

    Anyway, are there any serious issues with the ARC-3 build? Is it fairly stable?

    I'd like to submit it to the App Store as the 1.4.4 update if all-is-well.

  • Posts: 2,161

    Nothing I've done so far has come up with anything other than the New Project crash. I've not been doing anything too intensive, though: modified all my programs to work with a central library and fiddled around with Brickout.

  • Posts: 1,255

    It's been behaving fine for me, though I'm just refactoring code in the endless project and doing little to test new features.

    My problem with objective C is the somewhat obscure syntax and the 80's style memory management. I got enough of pointers and handles coding for the original Mac in '84. Though it provides fine control, I'd just as soon never malloc again.

  • SimeonSimeon Admin Mod
    Posts: 5,362

    @Andrew_Stacey but the ARC-3 build fixes the new project crash, right?

  • Posts: 2,161

    Yes! Sorry for not being clear.

  • Posts: 1,255

    I'm having an issue on the ARC-3 build where the fonts get lost after several code/run cycles. I can give you a screen shot if you like, but the result is that letters are replaced by smears, blocks, and semi-circles. One it happens, selecting a different font doesn't help. Exiting Codea, shutting it down, then restarting fixes the problem for another dozen or so cycles.

  • SimeonSimeon Admin Mod
    Posts: 5,362

    @Mark are you able to recreate this consistently? For example, pressing run 12 times or so?

  • Posts: 1,255

    Nope. It happens pretty consistently, but only after I've been coding for a good while. It seems to happen more quickly when I'm bouncing between projects, sipping snippets of code.

Sign In or Register to comment.