Objective C - Defining an instance variable when defining a property - objective-c

I saw this code snippet on the Internet (http://iphonedevelopment.blogspot.com/2008/12/outlets-property-vs-instance-variable.html):
#import <UIKit/UIKit.h>
#interface MyViewController : UIViewController {
UILabel *myLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *myLabel;
#end
My question is...When #synthesize is called isn't the UILabel instance variable created automatically? What is the point of creating the instance variable in the header file.. Can you get away with just the #property?

When #synthesize is called isn't the UILabel instance variable created automatically?
Yes.
What is the point of creating the instance variable in the header file.
Personal preference. Some developers (like me) prefer to see a complete picture of the state of a class. It helps to see what instance variables are available, as well as check that all instance variables are released correctly.
It's also a relatively new feature. Older code wouldn't expect automatically-generated instance variables.
Can you get away with just the #property?
No, you need to #synthesize to get an automatically generated instance variables A property value that's generated programmatically would not map directly to any instance variable.

#synthesize will create the instance variable but you will not be able to see it in the debugger which can be downright inconvenient.
Consider filing a bug with Apple about this.

Yes you can get away with just the #property in Objective-c 2.0.
see: Do declared properties require a corresponding instance variable?

Related

Noob properties error

I'm working with an existing code.
Here a popovercontroller has been declared in .h file and its giving me error in implementation line.
.h file
#property (nonatomic, strong) VFImagePickerController *imagePicker;
#property (nonatomic, strong) UIPopoverController *popoverController;
#property (nonatomic, strong) UINavigationController *targetVC;
.m file:
Please suggest how to fix this.
It appears that your class is a subclass of UIViewController. UIViewController has a private, undocumented ivar of _popoverController. Since you are trying to create an ivar in your class with the same name, you are getting an error.
The easiest thing to do is to rename your popoverController property to something different. Otherwise your app might get flagged for using a private API.
This problem occurs because your superclass, UIViewController, already has an instance variable named _popoverController. As a result, neither the default synthesis nor your explicit (commented) #synthesize directive have access to the instance variable that they want to use to provide the popoverController property.
You can resolve this by either renaming your property, or explicitly synthesizing the property to use a different instance variable name:
// Either
#property (nonatomic, strong) UIPopoverController *localPopoverController
// Or
#synthesize popoverController = _localPopoverController;
(Also note that the "local" prefix isn't necessarily best practice for your property names or instance variables; take a second to consider your preferred naming convention and pick a property/instance variable name appropriately.)
Uncomment the synthesize line and remove underscore to look like this: #synthetize popoverController;
And replace every _popoverController var name in your .m file to popoverController
Do not name your instance variable (or property) popoverController. As mentioned above UIViewController has an instance variable declared as _popoverController. (Who knows why.)
It would be wise not to give your popover controller a generic name anyway, because, for example, if you decide to add more than one popover to a toolbar, you'll have to create more than one popover controller to accomplish this.
If you look at Apple's sample code, you can see how they do this:
http://developer.apple.com/library/ios/#samplecode/Popovers/Introduction/Intro.html#//apple_ref/doc/uid/DTS40010436
Check out the private properties section in DetailViewController. There, you will see three controller objects and none with the generic name "popoverController”. That will cause problems.

"Strong" qualify in objc

I create a new project using xcode4.2, and view the AppDelegate:
#property (strong, nonatomic) UIWindow *window;
I know the strong is a new qualify in Xcode for ARC.However I didn't select using ARC while creating the project. As a result it is boring me.
Moreover,what does the below mean:
#synthesize window = _window;
Is _window a instance variable? But it didn't declare in the header file.I can understand if _window declared in the header but failed in this style.
Is it kind of modern obj-c runtime?
thanks!
strong is effectively the same as retain. I'm not sure if the compiler automatically translates that into retain for non ARC code or not. If not, it should generate a warning I would think.
#synthesize window = _window;
says the backing instance variable for the property window is _window. In the modern run time for iOS and 64 bit OS X, the instance variable is created automatically if you don't explicitly declare it in your header.

What is the difference between IBOutlet as a property or as a variable?

There are two different methods to declare IBOutlet.
In #interface section as variable:
IBOutlet UIButton *exampleButton;
Below the curve bracket but before #end of .h file as property:
#property (nonatomic, retain) IBOutlet UIButton *exampleButton;
What is the difference between these two methods and where should I use each one? Which method is better and in what cases?
Either one works fine in my experience. What doesn't work is declaring both the instance variable and the property "IBOutlet" -- that seems to really confuse things. If for some reason you want to avoid providing public access to your outlet, you can declare it as an instance variable and simply not create the property. On the other hand, now that the runtime will synthesize instance variables for you, many people are declaring only properties and skipping the explicit instance variable declaration; in that case, you'd obviously declare the property as the IBOutlet.
The #property combined with #synthesize setup the getter and setter methods for your objects. You should define it at least in the interface, and if you decide to create a property from it then you must also synthesize it the .m file.

Declaring IBOutlet inside or outside #interface?

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 ;)

Do declared properties require a corresponding instance variable?

Do properties in Objective-C 2.0 require a corresponding instance variable to be declared? For example, I'm used to doing something like this:
MyObject.h
#interface MyObject : NSObject {
NSString *name;
}
#property (nonatomic, retain) NSString *name;
#end
MyObject.m
#implementation
#synthesize name;
#end
However, what if I did this instead:
MyObject.h
#interface MyObject : NSObject {
}
#property (nonatomic, retain) NSString *name;
#end
Is this still valid? And is it in any way different to my previous example?
If you are using the Modern Objective-C Runtime (that's either iOS 3.x or greater, or 64-bit Snow Leopard or greater) then you do not need to define ivars for your properties in cases like this.
When you #synthesize the property, the ivar will in effect be synthesized also for you. This gets around the "fragile-ivar" scenario. You can read more about it on Cocoa with Love
In your interface, you can formally declare an instance variable between the braces, or via #property outside the braces, or both. Either way, they become attributes of the class. The difference is that if you declare #property, then you can implement using #synthesize, which auto-codes your getter/setter for you. The auto-coder setter initializes integers and floats to zero, for example. IF you declare an instance variable, and DO NOT specify a corresponding #property, then you cannot use #synthesize and must write your own getter/setter.
You can always override the auto-coded getter/setter by specifying your own. This is commonly done with the managedObjectContext property which is lazily loaded. Thus, you declare your managedObjectContext as a property, but then also write a -(NSManagedObjectContext *)managedObjectContext method. Recall that a method, which has the same name as an instance variable/property is the "getter" method.
The #property declaration method also allows you other options, such as retain and readonly, which the instance variable declaration method does not. Basically, ivar is the old way, and #property extends it and makes it fancier/easier. You can refer to either using the self. prefix, or not, it doesn't matter as long as the name is unique to that class. Otherwise, if your superclass has the same name of a property as you, then you have to say either like self.name or super.name in order to specify which name you are talking about.
Thus, you will see fewer and fewer people declare ivars between the braces, and instead shift toward just specifying #property, and then doing #synthesize. You cannot do #synthesize in your implementation without a corresponding #property. The Synthesizer only knows what type of attribute it is from the #property specification. The synthesize statement also allows you to rename properties, so that you can refer to a property by one name (shorthand) inside your code, but outside in the .h file use the full name. However, with the really cool autocomplete that XCode now has, this is less of an advantage, but is still there.
Hope this helps clear up all the confusion and misinformation that is floating around out there.
it works both ways but if you don't declare them in the curly braces, you won't see their values in the debugger in xcode.
From the documentation:
In general the behavior of properties is identical on both modern and legacy runtimes (see “Runtime Versions and Platforms” in Objective-C Runtime Programming Guide). There is one key difference: the modern runtime supports instance variable synthesis whereas the legacy runtime does not.
For #synthesize to work in the legacy runtime, you must either provide an instance variable with the same name and compatible type of the property or specify another existing instance variable in the #synthesize statement. With the modern runtime, if you do not provide an instance variable, the compiler adds one for you.
If you are using XCode 4.4 or later it will generate instance variable synthesizing code for you.
You just have to declare properties like below; it will generate synthesizing code and instance variable declaring code for you.
#property (nonatomic, strong) NSString *name;
it will generate synthesizing code as
#synthesize name = _name;
and you can access instance variable using _name
it is similar to declare
NSString* _name
but if you declare read-only property it like
#property (nonatomic, strong, readonly) NSString *name;
it will generate code
#synthesize name;
or
#synthesize name = name;
So you should access instant variable name with out prefix "_"
any way you can write your own synthesizing code then compiler will generate code for you.
you can write
#synthesize name = _name;
The Objective-C Programming Language: Property Implementation Directives
There are differences in the behavior of accessor synthesis that depend on the runtime (see also “Runtime Difference”):
For the legacy runtimes, instance variables must already be declared in the #interface block of the current class. If an instance variable of the same name as the property exists, and if its type is compatible with the property’s type, it is used—otherwise, you get a compiler error.
For the modern runtimes (see “Runtime Versions and Platforms” in Objective-C Runtime Programming Guide), instance variables are synthesized as needed. If an instance variable of the same name already exists, it is used.