Reputation: 718
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
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
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
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