What did manual reference counting look like, and which rules did ARC automate?

3.1.4 · L2 · Learning

Predict first

Under the manual-counting naming rules, which call returns an object you own?

// A: [array copy]
// B: [array objectAtIndex:0]
// C: [object description]
  • A
  • B
  • C

Mental model. Manual counting was keeping the sign-out sheet yourself. ARC is a robot clerk that follows the same rules without ever forgetting.

Before ARC, Objective-C programmers wrote the counting calls themselves: retain to take ownership, release to give it up, autorelease to hand something back without keeping it. The rule was “you own what you create”: methods whose names begin with alloc, new, copy or mutableCopy return an object you own and must release. Anything else you receive is borrowed (usually autoreleased), so retain it if you want to keep it.

ARC does not change the model; it automates the bookkeeping. The compiler applies the same naming conventions to decide where to put retains and releases, so Objective-C, Swift and mixed code share one scheme. The old bug classes remain recognisable as their ARC equivalents: a forgotten release is a leak (often a cycle now), and an over-release is a use-after-free that crashes.

copy belongs to the owning families, so the caller must release it. The others return borrowed (autoreleased) objects.

Common traps

  • Assuming ARC removed ownership rules. It follows them; the method-family names still matter when you annotate Objective-C APIs.
  • Treating copy as a cheap getter. By convention it returns a new object you own.

They might follow up with

  • What is a CF object’s equivalent? The Create and Copy rule (you own) versus the Get rule (you borrow). See the Unmanaged question.
  • Can a file opt out of ARC? In Objective-C, yes, with -fno-objc-arc. Swift always uses ARC.

Related questions

  • 3.1.5 What is an autorelease pool, and when does a Swift loop need one?
  • 3.6.3 What is Unmanaged, and what do takeRetainedValue and takeUnretainedValue mean?

← When exactly is an object deallocated: at the end of its scope, or…   What is an autorelease pool, and when does a Swift loop need one? →