I know but not exactly how all the arc works.
I know when to use weak properties to prevent memory leaks.
But I want to understand something else.
If I have UIViewController
with strong custom view inside him like this:
@property (nonatomic) UIView myView;
(the default is strong if we not specify anything).
If this view was weak, I know that don't need to care about releasing it, but what about strong?
Is it stay alive after my ViewController didDisappear / dealloc when it strong?
1. Should I set this view to nil in the viewWillDisappear?
2. Why when I create a weak property it's not exist anymore after I call its "init" method?
4 Answers
Let's see if we can help:
If I have
UIViewController
with strong custom view inside him like this:@property (nonatomic) UIView myView;
(the default is strong if we not specify anything). If this view was weak, I know that don't need to care about releasing it, but what about strong? Is it stay alive after my ViewController didDisappear / dealloc when it strong?
Don't think about reference counts or releasing, ARC really turns things around. The strong, weak, etc. attributes are associated with the variable, and you can understand this by taking a variable-centric view in which the variables are the actors - the entities controlling the lifetime of referenced objects.
Taking this view when a reference is stored into a variable which has the strong attribute then the variable informs ARC that it requires the referenced object to stay around.
Remove that reference from the variable; e.g. by overwriting it with another reference or with nil
; then the variable tells ARC it no longer requires the referenced object to stay around.
ARC itself simply keeps an object around as long as there is at least one variable which has told ARC that the object is required and has not yet withdrawn that requirement.
Your question is what happens when ARC removes an object which has instance variables which have the strong attribute. Taking the variable-centric view the question becomes: what happens when a variable itself is destroyed?
The answer is that the last act of a variable which has the strong attribute. and has a reference stored in it, is to tell ARC that the variable no longer requires the referenced object to be kept around.
- Should I set this view to nil in the viewWillDisappear?
You only need to set a variable which has the strong attribute to nil
if the variable itself will continue to exist long after you have need of the object that is referenced by the reference stored in the variable.
E.g. if you have a long living object which during its lifetime stores a reference to a large object for a short period in one of its instance variables then setting that variable to nil
at other times makes sense.
- Why when I create a weak property it's not exist anymore after I call its "init" method?
I assume here that you mean "create an object and store a reference to it in a weak property".
Staying with the variable-centric view a variable which has the weak attribute does not tell ARC to keep objects around, as one with the strong attribute does, rather it monitors the referenced object and when it goes away it sets itself to nil
.
If you create an object it will only be kept around by ARC as long as there is a reference to it stored in a variable which has the strong attribute. If all you do with the reference is store it in a variable which has the weak attribute there is no requirement for ARC to keep the object around.
Treating the variables as the actors above is of course an analogy, variables themselves are not active entities. What in reality happens is that during compilation the compiler inserts instructions which do the actions ascribed to variables above. The result is the same.
TL;DR: strong & weak are attributes associated with variables not with references. Consider the lifetime of the variables and what is stored in them to determine whether any objects are kept around or removed.
HTH
A strong reference (which you will use in most cases) means that you want to "own" the object you are referencing with this property/variable. The compiler will take care that any object that you assign to this property will not be destroyed as long as you point to it with a strong reference. Only once you set the property to nil will the object get destroyed (unless one or more other objects also hold a strong reference to it).
So, yes, you should set your strong properties to nil if you won't use it anymore.
Strong
as the name suggests are held by your class "strongly" that is to say as long as there is atleast one class holding a reference to that object, that object will never be released from memory. If the class that is holding the object with a "strong" gets deallocated, in your case your UIViewController
, then the object is automatically removed from memory and you don't have to set it to nil manually in dealloc. There is a famous example:
Imagine 5 kids are holding the balloon and all of them are holding it strongly. The balloon will never fly away as long as even one kid is holding onto it strongly. Now if there are 5 kids with just one holding onto the balloon strongly and others are holding onto it loosely(weak). The balloon will fly away as soon as the kid holding onto it strongly lets go. (I may be paraphrasing a bit but i hope you understand!)
So for your first point, you don't have to set it to nil everytime unless the situation demands it as it is done by ARC.
ARC is counting strong
references to an object. Whenever this count gets zero, the memory is freed immediately. You do not need to set references to nil
or use dealloc
.
If you initialize a weak
property like in your example, it gets freed immediately, as the strong reference count is zero.
weak
is used to break retain cycles. A typical example are delegates. In the following example ObjectA
has a strong reference to its delegate
(ObjectB
). This is a retain cycle, both objects are never freed:
@protocol ObjectADelegate <NSObject>
// requirements
@end
@interface ObjectA : NSObject
@property (strong) id<ObjectADelegate> delegate;
@end
@interface ObjectB : NSObject <ObjectADelegate>
@property (strong) ObjectA *instanceA;
@end
@implementation ObjectB
- (instancetype)init {
self = [super init];
if (self) {
self.instanceA = [ObjectA new];
self.instanceA.delegate = self;
}
return self;
}
@end
To fix this and break the retain cycle, you set the delegate property as weak
:
@interface ObjectA : NSObject
@property (weak) id<ObjectADelegate> delegate;
@end