summerc
summerc

Reputation: 1901

Strange assignment in synthesize

I have seen a lot of code like this

header.h

@interface Foo : NSObject
{
  NSString *str;
}

@property(nonatomic, retain) NSString *str;
@end

and then in implementation

@implementation Foo
 @synthesize str = _str;
@end

I can't understand what is the benefit of using such assignment ?

@synthesize str = _str;

Upvotes: 1

Views: 294

Answers (3)

Simon Germain
Simon Germain

Reputation: 6844

Here's a quick example of how it can be useful to use the name change:

@interface MyClass : NSObject {
    NSString *myString;
}

@property (nonatomic, retain) NSString *myString;

- (NSString *)stringTreatment:(NSString *)str;

@end

@implementation MyClass

@synthesize str = _str;

- (id)init {
    self = [super init];
    if (self) {
        self.str = [NSString string];
    }
    return self;
}

- (NSString *)stringTreatment:(NSString *)str {
    return [str uppercaseString];
}

@end

If you wouldn't have synthesized str as _str, you would get a warning in that stringTreatment method saying that the local declaration of str hides the instance variable.

Also, in your code, you could be assigning a value to _str and have an external class call [MyClass str] and it would return it.

So, to make a long story short, "str" remains the name of your property and "_str" is the internal reference to that property. For example, you won't be able to use [MyClass _str], that won't work. Makes sense?

Hope this helps.

Upvotes: 0

bandejapaisa
bandejapaisa

Reputation: 26952

It is just a common naming convention.

It is so that in your implementation, you can distinguish accessing a variable directly against accessing via the property accessor.

If you try and access str in your code, like [str length], the code won't compile. You either need to do [self.str length] or [_str length].

... and as it's an NSString immutable property, use copy, not retain.

Upvotes: 3

mattjgalloway
mattjgalloway

Reputation: 34912

@synthesize str = _str; will mean that the instance variable that is synthesised for the str property is called _str. In your code you therefore have a mismatch between it and the declared instance variable. So you'll actually end up with 2 instance variables, one called str and one called _str.

You want to do this:

@interface Foo : NSObject
@property(nonatomic, retain) NSString *str;
@end

@implementation Foo
@synthesize str = _str;
@end

Or this:

@interface Foo : NSObject {
    NSString *str;
}
@property(nonatomic, retain) NSString *str;
@end

@implementation Foo
@synthesize str;
@end

Or obviously rename the declared instance variable, _str.

There's lots of questions on SO already about whether or not to prefix with _ such as - Prefixing property names with an underscore in Objective C .

Upvotes: 3

Related Questions