1

I'm new to Objective C and I'm porting parts of an old (non ARC) framework to ARC. My question is, although ARC handles a lot of memory management behind the scenes now, are there any major memory management principles that I still need to be aware of to avoid leaks?

For instance I thought I read somewhere that in the 'main' function of an NSOperation subclass, the programmer should set up an 'autoreleasepool' for that function.

mbradber
  • 489
  • 5
  • 17
  • 1
    My book lists some common pitfalls: http://www.apeth.com/iOSBook/ch12.html#_unusual_memory_management_situations (section on unusual memory management situations, and note also preceding section on retain cycles) – matt Feb 18 '14 at 03:36
  • I disagree with the two 'too broad' close votes, although this may indeed be a duplicate. – Jasper Blues Feb 18 '14 at 03:57
  • Questions that solicit this kind of "pitfalls" or "features" information [don't work very well on Stack Overflow](http://meta.stackexchange.com/a/76492/159251); no one answer can be expected to be definitive and complete. We [end up with a list of equally valid](http://meta.stackexchange.com/a/56773/159251) forum-style posts, not one thing to read that has the verifiable answer to a problem. Thus, "too broad". @JasperBlues – jscs Feb 18 '14 at 04:03
  • @JoshCaswell If this kind of question doesn't work well, why does the duplicate have 152 votes? . . . still not convinced, I'm sorry. – Jasper Blues Feb 18 '14 at 04:25

2 Answers2

2

Probably the two biggest issues to watch for are 1) retain cycles, where x retains y and y retains x thus they're never freed. This usually happens with blocks. And 2) when using Core Foundation functions (Core Graphics etc), for example: CGImageCreate, CGImageRetain, CGImageRelease. You still need to manually manage the memory in those cases.

A common pattern to prevent retain cycles is to create a weak reference to one of the objects that would be in the cycle. (Often self). Such as this:

__weak typeof(self) weakSelf = self;
[self useBlock:^{
    typeof(weakSelf) strongSelf = weakSelf;
    // do something with strongSelf
}];

Notes: a) The reason you want to create a new strongSelf inside the block, is to ensure you're retaining the weakSelf variable for the duration of the block. Otherwise, you can have cases where weakSelf will become nil part way through the block. In some cases, you may want to add a test that strongSelf still exists immediately, and if not abort the block altogether. As weakSelf could become nil before the block starts.

__weak typeof(self) weakSelf = self;
[self useBlock:^{
    typeof(weakSelf) strongSelf = weakSelf;
    if (!strongSelf) return;
    // do something with strongSelf
}];

b) You only need to do this when self will be retaining the block (in this case via something the unknown useBlock method is doing).

Dave Wood
  • 13,143
  • 2
  • 59
  • 67
1

The programmer still needs to be 100% aware of retain/release, however, the compiler is doing 98% of the work. The 2% it can't do well is breaking retain cycle's, so it's helpful for the compiler to specify weak retention in properties or using the __weak modifier in select scenarios.

You may still setup your own @autoreleasepool's, too. The only time I've used them purposefully is in/as the body of a for loop, to force the memory to be reclaimed each iteration.

greymouser
  • 3,133
  • 19
  • 22