Skip to main content

Memory Management in iOS

The two basic rules of Memory Management are
  1. Objects obtained with -alloc-new-copy, or -mutableCopy have a retain count of one.
  2. For objects created with any other method, assume they have a retain count of one but will be autoreleased. If you need to keep them in memory, you need to explicitly retain them.
Lets see in detail how the memory management works,

Memory management concepts are of critical importance and every Cocoa programmer should take the time to master them.
Memory management in Cocoa comes in two flavors: classic retain counts and garbage-collected. The question deals with the retain count flavor, so I will focus on that one.
The retain count memory management scheme in Cocoa works on the basis that an object will remain in memory as long as other objects claim to be "interested in it." The Objective-C runtime keeps track of this "interested in" relationship with a simple number: the retain count. It does not matter who is interested in the object, only if anyone is interested in it. Objects that want to keep another object in memory ask that the other's retain count be increased by one, and if they are no longer interested in it may request that it be decreased by one. When the retain count for an object reaches zero, it means that no one is interested in it and it can be destroyed. The methods needed to alter the retain count of an object are inherited from NSObject:
- (id)retain;              // Increases the retain count of the object by 1

- (oneway void)release;    // Decreases the retain count of the object by 1

The oneway qualifier in the -release return type indicates that the caller will not wait for an answer from the method. This is required for a nifty technology called Distributed Objects, which allows an application to use objects from another process, even from a remote machine.
The value of an object’s retain count can be obtained with the method:
- (NSUInteger)retainCount;

The following snippets illustrate the basic use of these methods. Any class derived from NSObject and created with -alloc begins life with a retain count of one.
NSObject *anObject = [[NSObject alloc] init];

NSLog (@"Retain count = %d", [anObject retainCount]);    // Outputs 1

[otherObject doSomethingWith:anObject];

[anObject release];    // Done with the object





// Elsewhere in the program:

- (void)doSomethingWith:(NSObject *)anObject

{

    [anObject retain];

    NSLog (@"Retain count = %d", [anObject retainCount]);    // Outputs 2

    // ...

    [anObject release];

}

The example above begins by creating an object with a retain count of one. It is then passed to another method that increases its retain count, does some work with it and then releases it. At this point, anObject has a retain count of one again, so when it is released again after the -doSomethingWith:method returns, it will be destroyed.
You now know that whenever the retain count for an object reaches zero, it will be destroyed. This fact puts a burden of responsibility on you, the programmer. First of all, it means that if you release an object that already has a retain count of zero, your program will crash, because you will be sending a message to an object that no longer exists. Second, if you forget to release an object you no longer need, it will stay in memory while the program runs and waste resources. This situation is known as a memory leak.
When an object is released and reaches a retain count of zero, it is given the opportunity to clean-up after itself. This done by implementing the -dealloc method that is called just before the object is destroyed. In -dealloc you will typically release any objects or resources that are owned by the released object, so that memory leaks are prevented. A typical situation is given below.
- (void)dealloc

{

    [currentDate release];     // current date is an instance variable

    [myView release];          // myView is an instance variable

    [super dealloc];

}

Notice how the -dealloc method ends by calling the superclass's -dealloc. That is required and guarantees that clean-up continues all the way up to NSObject. The -dealloc method should never be invoked directly by the programmer. It must be called indirectly as a result of a -release message that decreases the retain count of an object to zero.
The final concept needed to complete this discussion of retain count memory management is autoreleased objects. The need for autoreleased objects arises from the situation illustrated by the method below.
- (MyObject *)returnsAnObject

{

    MyObject *foo = [[MyObject alloc] init];

    // Do something with foo

    return foo;

}

The -returnsAnObject method creates an instance of MyObject, manipulates it and then returns it. As written, the object is returned with a retain count of one. That may be OK, but it means that the object will have to be released explicitly later and this could cause confusion if the -returnsAnObject method is part of a library and you have no access to the source code. Adding a [foo release]; statement before returning will result in a crash because the object will be destroyed just before returning it.
The solution is to use the -autorelease method:
- (id)autorelease;    // Returns the object being autoreleased.

The -autorelease method means that the object will be released but later on, typically after the current user event is processed. For programming purposes, you can consider that an autoreleased object has a retain count of zero.
The previous example can then be amended to:
- (MyObject *)returnsAnObject

{

    MyObject *foo = [[[MyObject alloc] init] autorelease];

    // Do something with foo

    return foo;    // foo is returned with a virtual retain count of zero

}

******This tutorial is for my reference and is taken from informit
source: http://www.informit.com/blogs/blog.aspx?uk=Retain-Counts-for-Cocoa-and-iPhone-Programmers

Comments

Popular posts from this blog

User defined settings iOS

With User defined settings  we can set values specific to build configuration. Creating User Defined Settings Select Target > Build Settings Click Plus icon, present beside the search bar Using User Defined Settings when we need to access the values set in User defined build settings we can do it in two ways  From info.plist $(NEW_SETTING) From Code let value = Bundle.main.infoDictionary?["NEW_SETTING"] as! String

Advanced Debugging with Xcode and LLDB - WWDC 2018

Advanced Debugging Tips and Tricks: Injecting Code at runtime We can change values of variables at runtime while debugging (here variable_name is a Bool) expression variable_name = false  Here we are injecting value at runtime, so no need to run again to see the effect. (Other eg.,  expression animator.delegate = self) Under Xcode > Preferences > Behaviours > Running > Pauses > Check Show Tab Named, In order to show new tab while a breakpoint is hit. We can set other behaviours as well. We can add symbolic breakpoints on methods in frameworks. like This is in objective c because UIKit is in objective c. In order to find the values/parameter of a function inside framework, we can use For expression -[UILabel setText:] po $arg1 <UILabel ****> po (SEL)$arg2   "setText:" po $arg3 "0 ft" We can set symbolic breakpoints in 2 ways 1. By clicking plus in bottom left and choosing symbolic (Cons: Sets BP in all places) 2. By adding a breakpoi...