Sitemap

Memory Management in Objective-C: MRR and ARC

Yenat
5 min readMay 20, 2025

Memory management is the backbone of performance and stability of any system regardless of the programming language. The process of allocation of memory of objects when needed and deallocation when they’re no longer in use is called memory management.

From the manual retain/release days of Objective-C to Swift’s safety first ARC model, Apple has come a long way in simplifying this critical aspect of development.

Memory Management in Objective-C

In Objective-C memory is managed as follows:

  1. MRR (Manual Retain Release)
  2. ARC (Automatic Reference Counting)

1. Manual Retain Release(MRR)

MRR is also known as Manual Reference Counting (MRC). In Objective-C, all classes are derived from the root class NSObject (NS stand for NextStep, the platform where Objective-C originated) which provides methods for memory management. All NSObject classes are reference counted i.e Objects keep a track of how many times they are referenced by another object.

In MRR, memory management is the developer’s responsibility. When you create an object, you must explicitly manage its life cycle using two key methods: retain and release. Calling retain increases the object’s reference count by one. Conversely, calling release decreases the reference count, signaling that one less object is using it. An object remains in memory as long as its reference count is greater than zero.

MRR Basic Rules

In MRR, as the name suggests everything is done manually from creating an object, accessing it, retaining an object, releasing it and destroying the object. In order to avoid memory leakage and to the exact track of the reference count this are some of the things need to remember:

  1. One who creates the object is the owner of the object itself. If you create an object using alloc, new, copy or mutableCopy methods you own it, which mean you are responsible for calling release on it at some point to free memory.
`MyObject *obj = [[MyObject alloc] init]; // You own it, must release it later
[obj release]; // Done with it

2. You can own an object using retain method. If you get an object from some method that doesn’t use alloc, new, copy, or mutableCopy then you don’t own it by default. This means you’re not responsible to release it. But ownership can be achieved using retain method as if you have obtained the object with the above methods. Remember, if object is retained x number of times it needs to be released x number of times.

MyObject *obj = [someOtherObject getObject]; // You don't own this by default
[obj retain]; // Now you own it, This tells the runtime: “I want to keep this object around, so count me as one of its owners.”
[obj release]; // Later, you must release it

3. You must relinquish ownership of an object being owned once you’re done using it. This is done using either release or autorelease method.

  • release: Immediately decrements the object’s retain count
[object release]; // Immediate release
  • autorelease: does not release the object immediately it sends the object to autorelease pool and releases the object when the pool is drained. This typically happens at the end of the current run loop iteration, which is useful for temporary objects that should live just a bit longer
[object autorelease]; // Deferred release

4. Don’t release what you don’t own. Ownership implies responsibility: if you didn’t explicitly take ownership of the object (via alloc, new, copy, mutableCopy, or retain) then releasing the object can crash the application. Crash typically happens when;

  • You release an object that was already deallocated
  • you release an object that another part of the code is still using, causing premature deallocation

To avoid these issues, always follow the ownership rule: release only what you own, and retain only what you need.

2. Automatic Reference Counting (ARC)

Apple introduced ARC in 2011 with Mac OS X Lion and iOS 5 to simplify memory management for developers. ARC automatically inserts the necessary memory management calls such as retain, release, and autorelease at compile time based on how objects are used in the code.

ARC follows the same basic rules discussed above but with little modifications like ownership qualifiers. It reduces long code as the developer doesn’t need to write every retain or release, it also minimizes the risk of memory leakage as the compiler evaluates the life of the object itself.

Retain, release, autorelease or retainCount methods only work with MRR and not ARC. Also, errors show up if we use NSAutoreleasePool instead of @autoreleasepool block.

// Not allowed under ARC
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // error
// Correct way in ARC
@autoreleasepool {
NSString *tempString = [NSString stringWithFormat:@"Hello %@", @"ARC"];
NSLog(@"%@", tempString);
}

ARC Ownership Qualifiers

Ownership qualifiers tell ARC how to manage references to objects — wether to retain them, watch for their deallocation, or ignore safety entirely.

  • Strong: it increases the object’s retain count(i.e it takes ownership). As long as any strong reference exists, the object stays alive.

Default for object properties in ARC. Use it when you want to keep an object alive.

@property (strong, nonatomic) Person *person; // retains the object

// Usage
self.person = [[Person alloc] init]; // ARC retains it
  • Weak: Doesn’t increase retain count. If the object it points to is deallocated, the pointer is automatically set to nil. Use for references that shouldn’t keep alive (e.g delegates or parent child relationship)
@property (weak, nonatomic) id<SomeDelegate> delegate; // delegate won’t retain the controller
  • Unsafe_unretained: It also doesn’t retain the object. Unlike weak it doesn’t set the pointer to nil when the object is deallocated. If the object is deallocated and you access it through this reference your app will crash. Used mainly for backward compatibility (pre-iOS 5), or when performance matters and you’re 100% sure the object outlives the reference.
@property (unsafe_unretained, nonatomic) Person *legacyReference

Important:

The garbage collection principle is only available for Max OS X, starting with version 10.5. Also, iOS applications can’t use Garbage collection, since it depends on the power of the device it will take some time to process forcing the user to wait which leads to bad user experience. That’s why it is deprecated since OS X Version 10.8 in favor of ARC and scheduled to be removed in the forth coming versions of OS X.

Garbage collection works at runtime, but ARC inserts code at compile time, so the object deallocation is deterministic when the last strong reference is removed.

From juggling retains and releases to letting ARC do the heavy lifting, memory management in iOS has definitely leveled up. These days, the compiler’s got your back — but knowing what’s happening behind the scenes? That’s what separates the pros from the rest.

Stay tuned for more interesting and insightful iOS development content

--

--

No responses yet