XCode iPhone automatic property, synthesize and delloc - iphone

I have been developing for iPhone from last 1-2 months and all the time for taking IBOutlet I use the following method to declare any property:
In .h files:
#interface ....
{
controlType varName;
}
#property() IBOutlet controlType varName;
In .m files:
at top -#synthesize varName;
in delloc method - [varName release];
Although the method is good but it isn't very good when its taking a couple of minutes just for declaring property.
Is there any automatic process for declaring properties, IBOutlets, IBActions or basic data variables.
I hope there should be some automatic methods for this scenario as this is a very basic process.
Thanks all.

Another one that not many people are aware of is that you can drag from Interface Builder to your header file to create IBActions or IBOutlets.
NOTE: Open the Assistant Editor with focus on the XIB inside IB.
If you create your IBOutlets this way Xcode automatically adds the property, synthesizes it, sets it to nil in viewDidUnload and releases it in dealloc.
You simply drag from the IB object to your header file the same way you would when creating connections between the view objects and their file owners (screenshot below).

In fact, yes!
You no longer need to declare the actual iVar.
In short, simply leave out this part: controlType varName;
For now, you do still need to explicitly "synthesize".
(As far as I can see, they could possibly automate that in the future. But for now you have to "synthesize" to create the setter and getter.)
You do still have to release the memory - there's really no way that could be automated, as memory handling is "real he-man programming."
For any new chums reading, don't forget the "self." part when using the property.
Plus note that XCode4 even has a new automatic thingy. Simply drag from the interface builder, to your .h file, and it will do everything for you -- try it!
In answer to your suplementary question: An IBOutlet DOES NOT PARTICULARLY NEED TO BE a property - you can just use a normal cheap iVar. On the other hand, if you wish, to you can use a property. Furthermore: you can even use the new trick (2011) of not bothering to declare the ivar, just use the property declaration, and shove an IBOutlet in there!

There is an awesome tool that speeds the whole process up: accessorizer.
You write controlType varName; select it and press some buttons and accessorizer will create the property, init, dealloc, viewDidUnload and much more for you. You just have to paste the code into your project.
Try it, a demo is available.

You can save yourself having to release the object by changing the property declaration. If you use:
#property (assign) IBOutlet controlType varName;
retain wont be called on your view so you wont have to release it later. This is generally safe as views are retained when they are added to a parent. If you are removing the views from their parent for some reason then you will have to retain them.

Here's an xcode script to automate the tedium of declaring properties.

Related

How can I access various UIViews within a Nib, programmatically?

First, I am super-new to Objective-C/iOS development and, in fact, this question is for my first, test project. Also, I come from a C#/WinForms background so I'm coming into iOS development with certain pre-conceived notions of user interface design and application state. Please bear with me and help clear up my confusion.
I just created my first iOS application project which, consists of a Single View. I allowed Xcode to create all the files for me through the Single View project wizard. When it was finished, I opened my new applications, single UIView Nib file in the designer and I dropped three sliders onto the view.
The desired purpose of this application is very simple-- each slider corresponds to either the R, G or B values associated with the background color of my view.
I have figured out how to set the background of my view but I can not figure out how to access the values of each slider objects. Yes, I can hook-up and respond to an IBAction for each slider, but my plan is that each time a slider's value changes, I want the IBAction to call a refactored method that accesses the values of all three sliders and then set's the views Background Color based of the values associated with each one.
How can I access the values of my sliders? Specifically, how can I access the value of the sliders that I created by dragging and dropping them into the Nib designer window? I've seen code explaining how to programatically add a UISlider to your UIView and then access the value, but how do you access the value of a UISlider that's added to the Nib and, I assume, will be automatically "wired" in at compile time?
Hopefully this makes since? If I'm missing an intermediate step or critical concept, please let me know.
You create UISlider ivars/properties and make them IBOutlets:
#property (nonatomic, retain) IBOutlet UISlider* yourSlider;
You synthesize it in your .m file and the connect the IBOutlet in interface builder. The yourSlider pointer is then a reference to the object you connected it to. Note that it will only be loaded with the view of the UIViewController and therefore will be nil until viewDidLoad is called. You also must set it back to nil
self.yourSlider = nil;
in your viewDidUnload method (so that it is released). In Xcode 4 you have a convenient way of doing all the above steps in one action (see the "Interface Builder is Built-in" of What's new in XCode 4)
Similar to CTRL+dragging from the UISlider to the .m file to create the IBAction, you can CTRL+drag the UISlider from your .nib designer to the associated .h file and have it create a property for you. Then, from your .m file, you can access self.mySlider (or whatever you name the property).
There's a video on this page that shows binding to a UISlider specifically.
Another approach is to use the tag property of a view.
#property(nonatomic) NSInteger tag
- (UIView *)viewWithTag:(NSInteger)tag
You can set the tag property of a view in the interface builder and later reference that view in your controller.
UIView *myViewFromTag = [self.view viewWithTag:theNumberYouSetInIB];
In general, it's better to stick with IBOutlets. However, there are certain situations where it makes more sense to use tags.
Good luck!

Should every IBOutlet have a property?

We create property for a variable for using it in some other view. Same we do for IBOutlets. But not always for using them. Is it necessary to create property for each IBOutlet we just created it our xib? Or is it only a good practice to do so?
I like to look at it is in terms of ease of memory management, and external access. If you need to access it externally, obviously make a property. (Yes ease of memory management, if it's easy you won't mess it up, if you don't mess it up it doesn't become a bug later)
80% of the time my view controller has the IBOutlets and nobody else accesses them, therefore ivars work.
The problem is that when you don't use #property, the assigned value is still retained. Then you need to remember to release it even though you didn't retain it yourself, which I found counter-intuitive.
For that reason I usually use #property (assign) for the ones I won't be changing, and #property (retain) for everything else, and never declare IBOutlets directly as ivars.
Example:
#interface something : NSObject {
//This one needs to be RELEASED then set to nil in both viewDidUnload, and dealloc.
IBOutlet UILabel * myLabel;
//also cannot be accessed outside of "something" class (technically it can, but don't do that)
//I NEVER declare my outlets this way.
}
//This one can just be set to nil in viewDidUnload and dealloc
#property (nonatomic, retain) UILabel * myOtherLabel;
//it can also be accessed from mySomething.myOtherLabel by any other class.
//This one just works. I don't own it, the view owns it, so I don't retain/release.
#property (nonatomic, assign) UILabel * myOtherOtherLabel;
//It also provides access to outsiders.
//I wouldn't recommend using this type if you want to change the value though.
It is not necessary to create a property for each IBOutlet.
Specifically, if you access the outlet only from the class where it is declared, you do not strictly need the property. If you have a property, you get the advantages that properties offer, but you could always directly refer the outlet directly.
If you plan to access the outlet from another class, then a property is useful so you don't have to define yourself setter and getter methods.
If you want to use the IBOutlet for only the view for which you created the XIB then no need to set the property here. But yes, it is good practice to use but not mandatory to use everytime we create IBOutlet for the view.
If what you are going to display is not going to change, you can skip creating a property or a IBOutlet for that widget.
For example in a screen where you have a label and a textfield and the label always has the string "Name:" and textfield is used for getting input from the user, you have to just create a referencing outlet for the textfield to access the data input from the user. Creating a referencing outlet for label doesn't make any sense here.
I hope you get the point.
Properties are a feature in Objective-C that allow us to automatically generate accessors, and also have some other side benefits. so as Praveen S gave you an example with Label and UIText i just little explore.
Lets say you have nothing to do with UILabel you do not exactly need to set the properites but if are asking from user to give some text to your UITextField you have to set the properties. and if you setting the properties with retain, you must release it in viewDidUnload.
If you want to change the Contents of your display then you should add the property..for an example if we want to change the label text then we need to use IBOutlet nd Property so that we need to able to get to the label control that the framework will build from our nib..

Do IBOutlet member vars retain automatically?

Weird discovery, when I used a drag and drop to make a new IBOutlet, as shown below, not with a #property at all:
#interface SkinChoosingView : UIViewController {
IBOutlet UIActivityIndicatorView * activityIndicator;
}
Xcode inserted a -release and set the outlet to nil in viewDidUnload. I looked in viewDidLoad though, and no -retain was there! This went against everything I know about memory management.
I figure apple must know a thing or two about this stuff though, so is there something behind the scenes happening here? I have never had leaks from these types of IBOutlets, and I've never released them.
Yes, it automatically retains the outlet for you when loading the NIB file unless you explicitly declare the property associated with the outlet as an assigned property.
And since it retains the outlet for you, you must release in viewDidUnload as the outlets will be reloaded by the time next viewDidLoad is called.
The answer is that it uses "Key-Value Coading", which means it calls -setValue:forKey:, which has a "Default Search Pattern". For ivars, it does something like [ivar autorelease]; ivar = [newvalue retain];.
The "current best practice" is to stick IBOutlet on properties instead of ivars (see here). This makes it obvious what memory management pattern is being used and is more resilient to typos (e.g. if you misspell the ivar).

Retain counts of IBOutlets

While coding always the same questions concerning retain counts of IBOutlets came along: Retain count after unarchiving an object from NIB? When to use #property's for an IBOutlet? Retain or assign while setting? Differences between Mac and iPhone?
So I read The Nib Object Life Cycle from Apple's documentation. Some test apps on Mac and iPhone gave me some strange results. Nevertheless I wrote down a few rules how to handle this issue to stay happy while coding but now wanted to verify with the community and listen to your opinions and experiences:
Always create an IBOutlet for top-level objects. For non-top-level objects if necessary (access needed).
Always provide a property as follows for IBOutlets (and release them where necessary!):
Top-level objects on Mac:
#property (nonatomic, assign) IBOutlet SomeObject *someObject;
#synthesize someObject;
[self.someObject release];
Non-top-level objects on Mac (no release):
#property (nonatomic, assign) IBOutlet NSWindow *window;
#synthesize someObject;
Top-level objects on iPhone (must retain):
#property (nonatomic, retain) IBOutlet SomeObject *someObject;
#synthesize someObject;
[self.someObject release];
Non-top-level objects on iPhone (should retain):
#property (nonatomic, retain) IBOutlet UIWindow *window;
#synthesize window;
[self.window release];
Side notes:
On Mac and iPhone outlet connections are made with a setter if available.
Top-level objects: "have [...] no owning object"
Non-top-level objects: "any objects that have a parent or owning object, such as views nested inside view hierarchies."
So the question would be: is this correct and good practice?
I hope you can approve or correct it.
Always have your nibs' File's Owner be a subclass of NSWindowController or NSViewController (on Mac OS X) or UIViewController (on iPhone), and use #property (retain) IBOutlet for all of its outlets, doing appropriate releases in your controller subclass -dealloc method.
This pattern will work fine on both Mac OS X and iPhone OS, because NSWindowController and NSViewController on Mac OS X take implicit ownership of top-level objects for you (and relinquish that in their own -dealloc methods), and iPhone OS doesn't take any implicit ownership of top-level objects for you during nib loading.
Top-level objects: "have [...] no owning object"
Nix. Top-level objects are owned by the File's Owner, which is the File's Owner because it owns all the top-level objects in the file.
Windows have that option to release themselves as a convenience, but I find my design cleaner (even if it's a little more work) when I either turn it off and manage its lifetime myself, just like any other object I own, or use a window controller.
If you think this conflicts with the documentation you were quoting, let's go through the entire paragraph:
Objects in the nib file are initially created with a retain count of 1. As it rebuilds the object hierarchy, however, AppKit autoreleases any objects that have a parent or owning object, such as views nested inside view hierarchies.
Thus killing off its own ownerships. The nib loader doesn't want to own your objects.
By the time the nib-loading code is done, only the top-level objects in the nib file have a positive retain count and no owning object. Your code is responsible for releasing these top-level objects.
In other words, it's handing the ownership over to you.
The curious artifact of that is that you'll actually leak the object if your property to it has retain semantics. The documentation says you should retain it:
For both Mac OS X and UIKit, the recommended way to manage the top-level objects in a nib file is to create outlets for them in the File’s Owner object and then define setter methods to retain and release those objects as needed.
But if you do this, the object will remain alive even after you release your ownership of it.
I think I'll go file a bug about this. (Edit: Done. x-radar://problem/7559755) At the very least, the nib loader shouldn't be handing off two retentions, which it does in my test app (on 10.5.8 and 10.6.1).
From apple's doc mentioned above:
For both Mac OS X and UIKit, the recommended way to manage the top-level objects in a nib file is to create outlets for them in the File’s Owner object and then define setter methods to retain and release those objects as needed. Setter methods give you an appropriate place to include your memory-management code, even in situations where your application uses garbage collection. One easy way to implement your setter methods is to create a declared property (using the #property syntax) and let the compiler create them for you. For more information on how to define properties, see The Objective-C Programming Language.
Otherwise use #property(nonatomic, retain) IBOutlet * outletName;
I can write my opinion about iPhone NIB development:
If you use IB then use as many IBOutlets as possible (sometimes you don't know the views hierarchy when you build a NIB - it may be dynamic) or don't use them at all - otherwise there will be a mess
Use properties only if you want to access the views from outside the View Controller (if they should be public)
AFAIK there's no need to manage memory for IBOutlets
Hope it helps...
You should follow standard memory management guidelines. If your outlet is connected to a retained property, then you must release it in the -dealloc message.
And yes, you any top level objects not retained by any other objects usually need to be retained by yourself.
1) In general, why would you have a top-level object with no IBOutlet to point to it anyway? That requirement has never seemed very restrictive.
2) I think you got the settings about right for the iPhone. You can also use an assign property on the iPhone as well, which does what you would expect... but in general after a lot of use I prefer to use retain properties so I am 100% clear on when I consider the object released (especially with the viewDidUnload method to implement).
Also, just as a side note it's not good form to call [self.property release]. That leaves the reference intact but potentially invalid, if something else ever also releases the object... either say self.property = nil, or (better) set the underlying class variable to nil directly without using properties in dealloc statements (to avoid any possible side effects in dealloc).
As I mentioned in response to another poster, you can keep things clean by using IBOutlet properties declared in private class-local category extensions so they are not public properties. That looks like:
// in .m file
#interface MyClass ()
#property (nonatomic, retain) IBOutlet UIView *myPrivateView;
#end
#implementation MyClass
#synthesize myPrivateView;
.....

Does an IBOutlet needs to be a property & synthesized?

In most examples I see the following setup of IBOutlets:
(Example A)
FooController.h:
#interface FooController : UIViewController {
UILabel *fooLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *fooLabel;
#end
FooController.m:
#implementation FooController
#synthesize fooLabel;
#end
But this works also fine (notice: no property and no synthesize):
(Example B)
FooController.h:
#interface FooController : UIViewController {
IBOutlet UILabel *fooLabel;
}
#end
FooController.m:
#implementation FooController
#end
Are there any downsides of defining IBOutlets as in Example B? Like memory leaks? Seems to work fine and I prefer to not expose the IBOutlets as public properties as they are not used as such, they are only used in the controller implementation. Defining it in three places without a real need does not strike me as very DRY (Don't Repeat Yourself).
On Mac OS X, IBOutlets are connected like this:
Look for a method called set<OutletName>:. If it exists call it.
If no method exists, look for an instance variable named <OutletName>, set it without retaining.
On iPhone OS, IBOutlets are connected like this:
call [object setValue:outletValue forKey:#"<OutletName>"]
The behavior of set value for key is to do something like this:
Look for a method called set<OutletName>:. If it exists call it.
If no method exists, look for an instance variable named <OutletName>, set it and retain it.
If you use a property, you'll fall into the "Look for a method called set<OutletName>:..." case on both platforms. If you just use an instance variable, then you'll have different retain/release behavior on Mac OS X VS iPhone OS. There's nothing wrong with using an instance variable, you just need to deal with this difference in behavior as you switch between platforms.
Here's a link to full documentation on just this topic.
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW6
On Mac OS X, IBOutlets are not retained by defaults. This is the opposite of the behavior on iPhone OS: on iPhone OS, if you don't declare a property it is retained and you must release this property in the dealloc method. Additionally, the 64-bit runtime can synthesize instance variables using property declarations. That means that someday the instance variables (with the IBOutlet) may be omitted.
For these reasons it is more homogeneous and compatible to create always a property and use the IBOutlet only in the property. Unfortunately, it is also more verbose.
In your first example you always have to release the outlet in the dealloc method. In your second example you must release the outlet only with iPhone OS.
The end result is exactly the same, but you have to keep a few things in mind:
When using instance fields as outlets, you should NOT release them in dealloc.
When using properties that have the (retain) attribute, you have to release the property in dealloc (using self.property=nil or by releasing the backing variable). This makes it a lot more transparent as to what's going on.
Actually it all comes down to the same old rule: "thou shalt release what you alloc/retain". So in case you use an instance field as outlet, you didn't alloc/retain it, so you shouldn't release it.
Its possible that those examples use the retain because the sample code is programmatically allocating and initializing a UILabel and then adding it to the UIView. That's the case for many examples, since learning how to use Interface Builder is often not their point.
The second example (no property and no synthesize) with the IBOutlet is used when the developer 'assigns' the UILabel (Button, View, etc) within the Interface Builder -- by dragging the IBOulet to the Label or other View component. In my opinion, the preceding drag and drop action (Label onto View) also add the subview, the Label to a View -- and so on. Label is retained by a View; a View is retained by Window; Window is retained by File's Owner. File's Owner is usually your Document that is booted up in main.
You will note that when you step through your program (by adding an awakeFromNib
- (void)awakeFromNib
{
[fooLabel blahblah];
}
that fooLabel already has a memory address.
Thats because the Label was initialized from a file bundle (the nib file) using not init but initWithCoder. Which essentially deserializes the filestream to an object - and then sets the IBOutlet variable. (We're still talking about the IBOutlet method).
Also note that the aforementioned iOS method uses the Key Value method
call [object setValue:outletValue forKey:#"<OutletName>"]
which is the Observer/Observable pattern. That pattern require the Observable object reference each Observer in a Set/Array. A change in value will iterate the Set/Array and equally update all Observers. That Set WILL already retain each Observer thus the lack of retain in iOS.
Further and the rest is speculation.
It seems that cases when you do use Interface Builder then
#property (nonatomic, retain) IBOutlet UILabel *fooLabel;
should possibly be changed to
#property (nonatomic, weak) IBOutlet UILabel *fooLabel;
or
#property (nonatomic, assign) IBOutlet UILabel *fooLabel;
And then it needn't be released in a dealloc method. Plus it will satisfy the OSX and iOS requirements.
That's based on logic and I could be missing some pieces here.
Nevertheless, it may not matter if the view is persistent through the life of your program. Whereas a label in a modal dialog box (open, close, open, close) may in fact have over-retained and leak per cycle. And that's because (speculation again) each closed dialog box is serialized into a file system and thus persists x,y position and size, along with its subviews, etc. And subsequently deserialized ... on the next session open (Opposed to say minimiz or hidden.)