Lets see the traditional C ways for clearing up of unused objects is bit of a nightware. There is no ways in the language like how should be approached.
Imagine one function A create one object and pass it to another function B now both are using the same data now the problem is who is the responsible for deleting it, if its no longer used ? and lets say we have one function who is also gonna use the same data than what ?
Solution is there are conventions and design patterns to handle these situations, that’s the reason the reference counting was developed and management technique used in Obj-C.
What we have in Obj-C
Obj-C uses reference counting as its Memory Management Technique so according to that each object keeps an internal count of how many times its needed. So only incase of, if count drops to zero. Yes you can compare it with Garbage Collector we have in Java but its not like automatic some chunk of code getting executed and removing the objects which ones are not needed.
Most important thing is Object Ownership it means an object owner is someone that has explicitly said “I need that object, do’t delete”. So one object can have more than one owner.
If object owner are not using it they have the responsibilty to tell so that the reference count should be decreased by one. So while dealing with Obj-C pointers/Objects its really good to send correct messages.
alloc, it will allocates an fresh instance of the object, set the reference count +1.
new, shortest way to write alloc&init.
retain, you passed the object and you want to tell you need that so its reference count should be increased by 1 again.
autorelease, need object temporarily and want to delete once you done with the operations.
copy, creates new copy of the object.
dealloc, opposite of init method, automatically get called right before the object is destroyed.
Static methods used for allocating the initializing objects directly but be aware that you are not the owner of that object, once the scope of your program finish it will be removed. Ex: [NSString stringWithFormat:@”Say %@”,@”Hello”];
Its an instance of NSAutoreleasePool, objects which are to be autoreleased. You can also send message to autorelease or create object using convenience methods. So once the object added into autorelease pool and when the pool is popped, all the objects will be deleted.
Retain cycle is a condition where two objects strongly maintains a reference of each other and stops each other from being released. For example, let we have two classes as.
@interface Parent : NSObject
@property (nonatomic, strong) Child *child;
@interface Child : NSObject
@property (nonatomic, strong) Parent * parent;
So, at some point of time when creating object of any of these class as
Parent *parent = [[Parent alloc] init];
Child *child = [[Child alloc] init];
parent.child = child;
child.parent = parent;
Here the parent object maintaining a strong reference of Child class and child object maintaining a strong reference of Parent class in back. So, both parent and child objects having a reference count of one and one. Both objects will get released from memory only when their reference count will reach to zero but in this scenario this will not going to happen ever because both are mutually pointing to each other a dead lock is get created here. This situation is called the Retain Cycle that will lead to memory leaks.
Fortunately, it’s very easy to fix this problem—just tell one of the properties to maintain a weak reference to the other object so, what’s this weak and strong reference means??
Strong Reference: A strong reference says that don’t release this object till I m owing this.
Weak Reference: A weak reference says that don’t release this object until someone else pointing this strongly.
Just like strong and __strong, weak and __weak keywords are there for declaring properties and instance variables respectively as a weakly referenced object.
Quick Tips and common mistakes
Think about strong and weak pointers as well as retain cycles, Avoid unnecessary caching, Don’t declare every object globally unnecessarily, use Xcode Instruments such as static analyser and find the potential memory leaks and fix them
Arrays, Dictionaries and other objects that contains any object generally retain objects once you add it into them. It means once you create an object the reference count will be 1 and once you add it into an Arrays it wll be 2.
Releasing the Object that you do’t Own, lets say if creating an new object using convenience method than there is no need to release that.
Keeping and using an Object that you do’t Own.
Calling dealloc directly. So never call dealloc by the way you have to call init after calling alloc its kinda default constructor for init the default value of object.
Over-releasing. Accidentally you’re releasing something twice instead of once. You can also track these crashes by just enabling Zombies.
Retain Cycles. When an object released there is cascading effect, the root object released its childrens as well and so on. Lets say there is some condition like A owns B and B owns A as they own each other.