Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it needed to declare ivar and property with the same name?

In most project before Xcode 4.4, I realized that developers declared simultaneous an ivar and a property with the same name. Example

@interface SecondViewController : UIViewController
{
     NSString *string;
}

@property (strong, retain) NSString *string;

So I don't know why ?

like image 802
Proton Avatar asked Mar 02 '13 09:03

Proton


2 Answers

Just a matter of style and used to behavior from past compilers.

Now in newer compiler this is not required. As soon as you create a property an ivar is created behind the scene as well as it gets synthesized.

Compiler synthesizes with an alias as _propertyName, even you can opt to change this default behavior.

@interface AppDelegate : NSObject <NSApplicationDelegate>{
    NSString *bigString;
}
@property(strong)NSString *smallString;
@end

@implementation AppDelegate
@synthesize smallString=bigString;
-(void)awakeFromNib{
    self.smallString=@"hello";
    NSLog(@"%@",self.smallString);
}

@end
like image 118
Anoop Vaidya Avatar answered Sep 21 '22 16:09

Anoop Vaidya


I can't speak for others, but I don't use the same name. If I do declare an instance variable , it's with a leading underscore, so it's obvious if I'm referring to the instance variable or the setter/getter method.

With Xcode 4.4+ you don't need to declare the instance variable or call @synthesize and the compiler will automatically create an instance variable, with a leading underscore, and provide the setter/getter method for you.

However I don't think this mechanism is a very good idea, as it encourages developers to expose properties of the their class that should not be exposed.

For example, this is taken from Beginning iOS 6 Development:

@interface BIDViewController : UIViewController
@property (weak, nonatomic) IBOutlet UIButton *button;
- (IBAction)buttonPressed:(UIButton *)sender;
@end

Now, while I understand that you don't want to confuse a beginner with too many concepts at once, you have immediately violated Object Oriented Encapsulation by exposing both the UIButton object and the action method to users of this view controller, and neither should be exposed.

What happens, for example, if a using class does this:

BIDViewController *vc = ...;
vc.button = nil;

or

vc.buttonPressed(mySegmentedControl);

All hell breaks loose. Now while there are a 1000 ways to break a program and we cannot defend against all of them, we don't want to make an already weak system (Objective-C provides precious little in terms of defining who can and can't call one of your methods) weaker.

The above implementation is better done using private instance variables and methods, both of which are honoured by Interface Builder:

@implementation BIDViewController ()
{
    IBOutlet UIButton *_button;
}
- (IBAction)_buttonPressed:(UIButton *)sender;

@end

and any using classes will have a tougher time of breaking that model.

But of course this is more thinking and typing for a developer, and so Apple have introduced the new features so they can get what they want done in less time (there is very little typing when you simply drag an outlet to a header file and both the declaration and implementation skeleton is provided for you).

like image 35
trojanfoe Avatar answered Sep 18 '22 16:09

trojanfoe