1

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;
summerc
  • 1,871
  • 4
  • 18
  • 17
  • possible duplicate of [Prefixing property names with an underscore in Objective C](http://stackoverflow.com/questions/3521254/prefixing-property-names-with-an-underscore-in-objective-c) – rob mayoff Jan 27 '12 at 16:14
  • BTW make sure to read the most highly-voted answer to that question, not just the accepted answer. – rob mayoff Jan 27 '12 at 16:14

3 Answers3

3

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.

bandejapaisa
  • 26,576
  • 13
  • 94
  • 112
  • 1
    you can use retain... that has nothing to do with mutability. – Grady Player Jan 27 '12 at 16:22
  • 1
    @GradyPlayer retain is not a good idea for objects with a mutable subclass, since a mutable object can be changed without your knowledge. its safer to use copy – wattson12 Jan 27 '12 at 16:52
  • @GradyPlayer http://stackoverflow.com/questions/387959/nsstring-property-copy-or-retain – bandejapaisa Jan 29 '12 at 09:50
  • I am all for best practices but I disagree with this for a couple of reasons, in that there are many situations where that doesn't hold up. Ie copy only modifies the assignment not the getter, copy can simply retain and return, it isn't required by convention to be distinct. And encapsulation should indicate that the class should only had out pointer to objects that are safe to hand out... – Grady Player Jan 30 '12 at 17:48
3

@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 .

Community
  • 1
  • 1
mattjgalloway
  • 34,792
  • 12
  • 100
  • 110
0

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.

Simon Germain
  • 6,834
  • 1
  • 27
  • 42