Shyngys Kassymov
Shyngys Kassymov

Reputation: 718

Do I need variable and property at the same time?

I'm new in iOS development, and have trouble in understanding of some cases. My question is do I need variable and property at the same time?

For example I saw code like this:

#import <Cocoa/Cocoa.h>

@interface Photo : NSObject {
    NSString* caption;
    NSString* photographer;
}
@property (retain) NSString* caption;
@property (retain) NSString* photographer;

@end

But, as I know, if I delete variables caption and photographer code still will work:

#import <Cocoa/Cocoa.h>

@interface Photo : NSObject

@property (retain) NSString* caption;
@property (retain) NSString* photographer;

@end

So, please explain the difference of using first one and second.

Thanks, for any advices!

Upvotes: 2

Views: 110

Answers (3)

David Wong
David Wong

Reputation: 10294

Variables inside the {} parenthesis are instance variables. They're accessible only to the class.

@property defines a few different things denoted by the (options).

Most people use @property to convenience methods inside your .m and .h files. For example

@property (strong) NSString *string;

Creates two methods inside your .h and .m file, invisible to you though, called:

-(NSString *)string; //returns the string object
-(void)setString:(NSString *)string;

So what it does is improve readability and helps reduce a lot of boiler plate code.

It's no longer necessary to define the instance variable inside the {} parenthesis now.

If you need to have the instance variable set to a different name you can put a

@synthesize string = _string;

Since you're new at this Ill add some bonus stuff for you to think about. self.string = @"string" May not be an equivalent call as string = @"string"

If you have @property (strong) NSString *string; and @synthesize string; The reason for this is setting the string via self.string is using the method implementation to set the string and may be overridden like this:

-(void)setString:(NSString *)str{
    string = [NSString stringWithFormat:@"%@.jpg", str];
}

So self.string = @"hello" would be @"hello.jpg" where as string = @"hello" is just "hello"

Also self.string = @"string"; is much the same as [self setString:@"string"];

For clarification on what @property(strong)NSString *string does inside the .h adds:

{
   NSString *_string;
}
-(void)setString:(NSString *)string;
-(NSString *)string;

inside .m:

-(void)setString:(NSString *)string{
_string = string;
}

-(NSString *)string{
return _string;
}

So there's no need to call @synthesize unless you want to rename the iVar into something else @synthesize string = wibblyWobblyTimeyWimey;

so in the .h it would be

{
NSString *wibblyWobblyTimeyWimey;
}

inside the .m

-(void)setString:(NSString *)string{
wibblyWobblyTimeyWimey = string;
}

-(NSString *)string {
return wibblyWobblyTimeyWimey;
}

Upvotes: 2

maz
maz

Reputation: 8336

If you're using Xcode 4.6.x, and you've installed the command-line tools with Clang 4 or higher, you can take advantage of 'auto-synthesized' properties.

@interface Photo : NSObject

@property (retain) NSString* caption;
@property (retain) NSString* photographer;

@end

Will give you the instance variables _caption and _photographer. So no, you really don't need to declare instance variables in most cases. If you're using ARC, it would only make sense to use properties.

Here is what that code should look like if you're using ARC:

@interface Photo : NSObject

@property (strong) NSString* caption;
@property (strong) NSString* photographer;

@end

Also, generally it's a good idea to specify the nonatomic attribute. Not doing so will mean that the accessors that clang will generate will be using locks:

@interface Photo : NSObject

@property (strong, nonatomic) NSString* caption;
@property (strong, nonatomic) NSString* photographer;

@end

Upvotes: 1

Schrodingrrr
Schrodingrrr

Reputation: 4271

No you do not. The variable in the {} are private members, not accessible to classes that inherit this header file, whereas properties can be access, read, and written, by inheriting classes.

But this is not always the case. In certain cases, (like delegates), both are required.

Upvotes: 0

Related Questions