3

I have read many articles online, and I am a bit confused about ARC. I will list my questions below, please help me answer them.

1.) What does the keyword strong do (in @property (nonatomic, strong) …)?

2.) Don't we have to release or autorelease what we alloc anymore, because I get a warning saying that I need not have to. (I am not at my Mac, so I can't copy the warning I got.)

3.) I couldn't find the Leaks tool in Xcode 4.2. Where did it go? Or don't we have to check for leaks anymore?

4.) When creating the project using Xcode 4.2, I clicked on "enable ARC", so will my program work on iOS 3? (I think ARC only supports iOS 4 and above.)

Nick Toumpelis
  • 2,717
  • 22
  • 38
sharon
  • 580
  • 12
  • 28

3 Answers3

7
  1. strong is an ARC analog to retain (there's no retain under ARC). It means that property value will be hold by class where the @property was defined, and released upon reassignment or dealloc. (Note that under ARC there's no need to release or nullify properties in dealloc).

  2. The point of ARC is taking care of retain/release routine by compiler, so there's no need for manual memory management methods.

  3. You can check for leaks by running Profile (Product -> Profile menu) and selecting Leaks instrument. Leaks can be introduced with cyclic references or in CoreFoundation code (ARC doesn't work with CoreFoundation). Also if you are mixing ARC and non-ARC code, the latter could be a source of leaks.

  4. ARC is supported by OS starting from iOS 4.0 (though iOS 5 SDK is needed). The key difference between 4.0 and 5.0 ARC support is availability of weak property specifier. Weak property (__weak variable) will be automatically nullified when the strong value it refers to is released. There are no weak properties in 4.0, so __unsafe_unretained specifier should be used (It's a close analog to assign specifier, it doesn't retain value and can point to already deallocated value, so it's dangerous).

Here's a great explanation of ARC: Everything you need to know about automatic reference counting

iHunter
  • 6,205
  • 3
  • 38
  • 56
  • ARC is supported for iOS4.3 onwards - not 4.0. – Abizern Dec 19 '11 at 18:37
  • ARC doesn't work with CoreFoundation, so leaks could be introduced in CF code. Also if you are mixing ARC and non-ARC code, the latter could be a source. – iHunter Dec 19 '11 at 18:38
  • 1
    I'm a bit late here, but ARC is actually supported starting iOS 4.0, not 4.3. – danyowdee Dec 26 '11 at 12:22
  • @danyowdee Seems you are right. I've found a discussion in comments to an answer stating 4.0+ is supported either: http://stackoverflow.com/a/7747801/153651. – iHunter Dec 26 '11 at 12:40
  • @Abizern Looks like you were wrong with arc on 4.0 (see a discussion by the link in a comment above) – iHunter Dec 26 '11 at 12:47
6
  1. Strong is equivalent to retain in ARC. It indicates ownership: What does the "strong" keyword do

  2. No, that's done for you. ARC inserts those statements in (compiled) code automatically. That's its main job. But, per Abizern's comment, this only works for your objects and Cocoa objects. If you're using Core Foundation (CF*) classes then you must read about the __bridge family of casts. You might start reading here.

  3. It's in Instruments. Per iHunter's answer, Cmd+I or Product->Profile, then choose Leaks. Particularly important given (2).

  4. It will not work.

Community
  • 1
  • 1
Tim
  • 5,024
  • 2
  • 30
  • 58
  • 1
    +1. Regarding #2, you shouldn't be getting a warning; you should be getting an error. It's not that you don't have to use `release`. It's that you *must* not use `release`. – Rob Napier Dec 19 '11 at 17:53
  • So do we still have to test for leaks ? If ARC is releasing memory then why should we test for leaks? – sharon Dec 19 '11 at 18:29
  • 1
    ARC only deals with Cocoa objects. If you are using Core Foundation objects you still have to use memory management. There are rules for transferring ownership of objects when using toll-free bridging. ARC doesn't make memory management go away - it just makes the more common parts of it easier and more efficient. So, yes - you still need to check for leaks. – Abizern Dec 19 '11 at 18:36
  • Also if you have cycles in your object graph, they will not be deallocated. – Catfish_Man Dec 20 '11 at 03:06
2

Well, there are already three answers that cover the main things so I'll focus on a single detail here, that isn't already mentioned:

3.) I couldn't find the Leaks tool in Xcode 4.2. Where did it go? Or don't we have to check for leaks anymore?

Yes we do still need to check for leaks:

ARC is not garbage collection, it is automated retain/release.

Thus, it is still possible — in fact, it's pretty easy — to create leaks!

Consider the following example:

@class Puppet;
@protocol PuppetDelegate : <NSObject>
- (void)puppetDidTwistStrings:(Puppet *)puppet;
@end

@interface Puppet : NSObject {
    id <PuppetDelegate> delegate_;
}

- (id)initWithPuppetDelegate:(id <PuppetDelegate>)delegate;
- (void)unravelStrings;

@end

@implementation Puppet
- (id)initWithPuppetDelegate:delegate
{
    if (!(self = [super init])) return nil;

    delegate_ = delegate;

    return self;
}

// assume some implementation for unravel strings

@end

@interface MasterOfPuppets : NSObject <PuppetDelegate> {
    NSMutableArray *puppets_;
}

- (void)puppetDidTwistStrings:(Puppet *)puppet;
- (void)bringOutAPuppet;

@end

@implementation
- (id)init
{
     if (!(self = [super init])) return nil;

     puppets_ = [[NSMutableArray alloc] init];

     return self;
}

- (void)bringOutAPuppet
{
    Puppet *newPuppet = [[Puppet alloc] initWithPuppetDelegate:self];
    [puppets_ addObject:newPuppet];
}

- (void)puppetDidTwistStrings:(Puppet *)puppet
{
    BOOL isOurPuppet = [puppets_ containsObject:puppet];
    if (!isOurPuppet) return;

    [puppet unravelStrings];
}
@end

This example is (admittedly) a little stupid, but this code will leak, and ARC is not going to help you about it, whereas garbage collection would:

  • A MasterOfPuppets can have many puppets, which he stores in an instance variable — so far so good.
  • A Puppet has a delegate which it is going to inform if its strings are entangled — and here it starts.

Whereas in non-ARC code an instance variable was simply a pointer that was being assigned to, ARC assumes that if you stash something in a variable, you want to cling on to it and it will retain the value unless you tell it not to.

So you have a classical retain-cycle here and ARC won't save you from those.

This may seem a contrived and far-fetched example, but it's not: I've seen this quite a bit in delegate relationships.

(The solution, by the way, is pretty simple: declare Puppet's delegate_ instance variable as weak and everything works as it should.)

danyowdee
  • 4,658
  • 2
  • 20
  • 35
  • To be honest, this problem (cyclic reference leaking) exists even in GC environments. It's hard for GC to decide which link to break first. – iHunter Dec 19 '11 at 20:45