If I tie some interface builder objects to another object as instance variables, do they need to be released in dealloc method of the parent object? The important point is that I declare my IBOutlets with key-value coding(#property) in (nonatomic, retain) mode. In my theory IBOutlet objects is created when initWithNibName:... method of my view controller is called and it is retained by the parent object because I implemented an #property method in retain mode. Is this correct? What about if I implement the method in assign mode?
Absolutely correct. You have to release the (retain) properties in dealloc, IBOutlet or not. This way memory management for IBOutlets is clearly defined.
If you wire up IBOutlets from objects that are already retained (e.g. subviews of otherwise retained views), you can also use (assign) for your properties (and, of course, not release them in dealloc).
Related
This question already has answers here:
Should IBOutlets be strong or weak under ARC?
(11 answers)
Closed 8 years ago.
When declaring a button, there are always two options as properties for the button:strong and weak. What is the difference between them? Also, what it nonatomic? For example:
#property (weak, nonatomic) IBOutlet UIButton *MyButton;
Got this all from http://clickflickboom.com/strong-vs-weak/...
You have a choice between (strong) and (weak) when defining a property. In this post I’ll explain the difference between the two.
Strong
#property (strong) NSString *myString;
This is the default state of a pointer, though I still like to explicitly state strong for clarity. A strong pointer will be retained as long as the class in which it was allocated remains.
Weak
#property (weak) NSString *myString;
A weak reference means the pointer has no owner, therefore it will be deallocated as soon as it is no longer needed (that is, nothing else is pointing to it).
Most commonly, you would use weak for IBOutlets, such as UITextFIeld, UILabels and UIButton objects. Here’s an example:
In this case, I’m creating an IBOutlet for a button (theButton) in my view within my controller. The theButton object belongs to my view, not my controller, so in this case a weak attribute makes more sense than strong. In fact, as a general rule IBOutlets should always be set to weak.
please read this:
Should IBOutlets be strong or weak under ARC?
From a practical perspective, in iOS and OS X outlets should be defined as declared properties. Outlets should generally be weak, except for those from File’s Owner to top-level objects in a nib file (or, in iOS, a storyboard scene) which should be strong. Outlets that you create will therefore typically be weak by default, because:
Outlets that you create to, for example, subviews of a view controller’s view or a window controller’s window, are arbitrary references between objects that do not imply ownership.
The strong outlets are frequently specified by framework classes (for example, UIViewController’s view outlet, or NSWindowController’s window outlet).
#property (weak) IBOutlet MyView *viewContainerSubview;
#property (strong) IBOutlet MyOtherClass *topLevelObject;
Though I'm sure they exists, I'm having difficulties finding or pinning down an official best practice for declaring outlets in a ViewController.
There are 3 options so far as I can see:
ivar only
property only
property backed with an ivar
Xcode currently crashes when I try and auto-generate a property by dragging into my ViewController from IB, but from what I remember, doing so creates a property without an ivar. It is also possible to drag into the ivar section and this will create an ivar without a property. This suggests that property-only and ivar only outlets are both OK with apple.
So in viewDidUnload we need to assign nil to any of our outlets, but what about dealloc. If we have used a property without an ivar, how can we release our outlet give that we are not supposed to use any accessors in an init or dealloc?
It seems to me that the only pattern which would allow us to release our outlet without an accessor is using a property backed with an ivar, so we can manually release our ivar in dealloc without using its accessor, however this is the one option which Apple's code-generation doesn't support.
As a rule of thumb, I usually create accessors for IBOutlets.
In ARC or non-ARC projects I usually do the following:
//.h (ARC)
#property (nonatomic, weak) IBOutlet UILabel* myLabel;
//.h (non-ARC)
#property (nonatomic, retain) IBOutlet UILabel* myLabel;
//.m
#synthesize myLabel;
In this manner you can let the compiler to create an instance variable for you. But you can also declare your instance variable and tell the compiler to use that.
Then you can use that accessors/instance variable wherever you want.
The Apple Memory Management guide says that you have to avoid accessors methods in init or dealloc methods when you have non-ARC projects. So, for example:
// (non-ARC)
- (void)dealloc
{
[myLabel release]; myLabel = nil; // I'm using the instance variable here!
[super dealloc];
}
This is very important in non-ARC projects. The reason is that, if there is no accessor, KVC will assign the nib object to the instance variable and will put a retain on it. If you forget to release it, you could have a memory leak. Using an accessor force you to release that object at the end.
I strongly suggest to read friday-qa-2012-04-13-nib-memory-management by Mike Ash. It's a very cool article on nib and memory management.
Hope it helps.
Here's my understanding
Use properties for variables that will be accessed by other classes, either read from (getters) or written to (setters). Both setters and getters are synthesized for properties.
Use ivars for variables that will be used internally by the owning class only, that is, other classes will not set or get their values.
Sure you can use properties in lieu of ivars, but they incur the function-call overhead whenever they're accessed. So if you have an internal variable that is accessed by your class a LOT, the function calls will affect the real-time performance, and this can be avoided by declaring them as ivars.
Just starting out with ARC. Pre-ARC, I would just simply declare my outlets as for example: IBOutlet UIButton *button; so I am not retaining it or anything. With ARC, not specifying weak or strong implies strong.
So if I do the same thing under ARC (i.e. IBOutlet UIButton *button;), does this mean button is a strong reference? or Do I have to explcility define it as weak?
In short, does IBOutlet imply __weak?
The word IBOutlet is actually defined as nothing:
#define IBOutlet
Xcode just uses the presence of this word in your code for purposes of allowing you to make connections in Interface Builder. A declaration of a variable or a property as an IBOutlet:
IBOutlet UIButton * button;
#property (...) IBOutlet UIButton * button;
therefore doesn't have any direct effect as far as ARC is concerned; it doesn't (although, conceivably, it could) translate into __weak or anything like that. The word itself is entirely gone from your source by the time the compiler gets it.
On the other hand, the fact that this variable or property is an outlet does have a meaningful effect on how you need to think about the memory management.
The implicit storage qualifier for an object variable declaration like IBOutlet UIButton * button; under ARC is __strong, as you said -- any object assigned to the variable will be considered "owned". Under MRR, the declaration is just a pointer; assigning to has no effect on the reference count/ownership of the assigned object -- it acts in the same way as an assign property.* So the meaning of the same ivar declaration changes between the two management systems.
Objects in a xib have owned/owner relationships that are formed by the view hierarchy; that is, parent views own their subviews. The top-level view in a xib is owned by the object known as File's Owner. This setup means that, generally speaking, your outlets to objects in an xib that are not top-level should be weak (under ARC) or assign (if a property under MRR). They are not owning relationships; they are essentially convenient indexes into the view list. This is Apple's recommendation:
...you don’t need strong references to objects lower down in the graph because they’re owned by their parents, and you should minimize the risk of creating strong reference cycles.
[...]Outlets should generally be weak, except for those from File’s Owner to top-level objects in a nib file (or, in iOS, a storyboard scene) which should be strong. Outlets that you create should will [sic] therefore typically be weak by default...
Your simple pointer IBOutlets, as I explained, acted -- for memory management purposes -- like weak properties,** which means that they were doing the right thing. The same declaration becomes probably the wrong thing when compiled under ARC.
In summary: IBOutlet does not translate into weak, but it does change the meaning of the pointer. Since the default memory management semantics of IBOutlet UIButton * button; change from "assign" under MRR to "owned" under ARC, and since IBOutlets should generally be non-owning, the presence of IBOutlet does indeed imply that the pointer should be declared __weak under ARC.†
*And similar to a weak property -- the only difference there is that weak pointers are set to nil when the object is deallocated.
**Except for the auto-nil part.
†Or, really, it should be a weak property.
No, IBOutlet is basically stripped when the code is compiled. It is however a helper for XCode so that it can know WHAT is an InterfaceBuilderOutlet.
Basically this word will let you connect the element in the Interface Builder.
By default it will still be strong (just imagine that word isn't there).
However it is suggested that you set it to weak because once something is connected to the interface builder, THAT interface will keep a strong reference to it, so there is no point at having a double strong reference, specially if that element is not meant to be kept alive when the interface has been unloaded.
Read this question which is exactly what you are looking for:
Should IBOutlets be strong or weak under ARC?
The IBOutlet keyword is only used to associate the object with an element in Interface Builder. It has nothing to do with weak or strong or ARC or memory management.
I am keeping a reference to the example object but I never use retain, new, or copy.
#interface ExampleViewController : UIViewController
{
IBOutlet UILabel *example;
}
#end
If I connect a UILabel object in Interface Builder to example, the retain count is two. But when I don't connect it, the retain count is zero. I would think that I am keeping one reference and the view is keeping another, therefore I would need to release it. What do you think?
IBOutlet instance variables are a special case. In iOS, each IBOutlet instance variable is retained when the NIB is loaded, so you do need to release them yourself.
In fact, you should take special care to release and nil these IBOutlets in -viewDidUnload:, otherwise they'll leak when the NIB is reloaded.
Note that this is actually different from Mac OS X development, where IBOutlets are not retained unless it's a top-level NIB object without a parent view or window.
For this reason, Apple now recommends exposing IBOutlets via properties rather than instance variables. That way, the ownership of the outlet is clearly defined.
#property (nonatomic, assign) IBOutlet UIButton* myButton;
#property (nonatomic, retain) IBOutlet NSObject* someObject;
myButton would not have to be released; someObject would have to be released. And in both cases, you're responsible for cleaning up these variables in -viewDidUnload:.
If you’re using ARC, then you don’t need to release an instance variable, as it’ll be released when your instance is deallocated. If you aren’t using ARC, you should write your -dealloc method in ExampleViewController as such:
- (void)dealloc
{
[example release];
[super dealloc];
}
Note that if you set example manually without using ARC, it is not automatically retained. Since you’re using a nib, however, it will be retained when it’s set up.
You need to release them in - (void) dealloc if you're not using ARC and there is a property for your IBOutlet, and you need to release and nil them in viewDidUnload:.
Consider using ARC (Automatic Retain Counting) for you project. With ARC the compiler takes care of retain counts so you don't have to, in fact aren't allowed to. There is a refactoring that will convert a current project.
sorry If am I being too picky on this one but I am learning iOS programming now and I've seem some people who declare the IBOutlet like this:
IBOutlet attached to property
#import <UIKit/UIKit.h>
#import "CustomCell.h"
#interface CustomTableViewController : UITableViewController {
CustomCell *customCell;
}
#property (nonatomic, retain) IBOutlet CustomCell *customCell;
#end
And some declaring like this:
IBOutlet attached to the declaration inside the interface
#import <UIKit/UIKit.h>
#import "CustomCell.h"
#interface CustomTableViewController : UITableViewController {
IBOutlet CustomCell *customCell;
}
#property (nonatomic, retain) CustomCell *customCell;
#end
which one is the proper way to declare it? Are any differences between them?
If someone know to explain why do they put it on different places it would be awesome to learn.
Thanks a lot :)
Both of those are still "inside the interface" so your title it a bit confusing but I see what you are asking.
In many cases the result of either approach will be the same but they are different. An IBOutlet property will call the property's setter method which gives you an opportunity to override that setter if setting that property should have some side effect.
I prefer to use outlets on properties because I think it makes the memory management of the objects loaded from the nib much clearer. Take a look at memory management of nib objects and I think you will see what I mean.
Objects in the nib file are created with a retain count of 1 and then autoreleased. As it rebuilds the object hierarchy, UIKit reestablishes connections between the objects using setValue:forKey:, which uses the available setter method or retains the object by default if no setter method is available. This means that (assuming you follow the pattern shown in “Outlets”) any object for which you have an outlet remains valid. If there are any top-level objects you do not store in outlets, however, you must retain either the array returned by the loadNibNamed:owner:options: method or the objects inside the array to prevent those objects from being released prematurely.
IBOutlet ivars will call setters for those ivars if they exists and directly retain the object loaded from the nib if no setter is found.
Advertising the property as the IBOutlet at least makes it clear that the property's setter will always be used and follow whatever memory management rule has been set for that property.
Finally I argue that IBOutlets are part of the public interface of a class and it is therefore better to expose methods (via a property) for working with them eager than using -setValue:forKey: to manipulate the backing ivars which should be an implementation detail.
The two styles are interchangeable, there is no difference in the generated code or the way objects will be loaded from a nib. Really.
However, both styles have a redundant line. Simply leave out the ivar declaration. Just the line
#property (nonatomic, retain) IBOutlet CustomCell *customCell;
is sufficient in the modern runtime.
If you have a complex project, I suggest moving all the outlets out of the public interface into a separate header file. Most outlets are private interface, the only reason to have them in a header is so Interface Builder can find them.
You can declare both ways, there is no difference actually.
But, here is the thing:
If you need your class to have some ivar with a special behavior or it has to be accessed from outside, etc, and it has to be a property, then I will say you have 2 options to choose from (attached to the property and inside the class interface).
If that is not your case, don't create a property, is not necessary, just do it inside your class interface.
Hope it helps ;)