Say I have the following:
@interface MyClass : NSObject { NSString* _foobar; }
@property (nonatomic, retain) NSString* foobar;
@end
@implementation MyClass
@dynamic foobar;
- (void) setFoobar:(NSString*)fbSet; { [_foobar release]; _foobar = [fbSet retain]; }
- (NSString*) foobar; { return _foobar; }
@end
Then:
MyClass* mcInst = [[[MyClass alloc] init] autorelease];
NSLog(@"I set 'foobar' to '%@'", (mcInst.foobar = @"BAZ!"));
Looking at the return value of -[MyClass setFoobar:]
, one might assume here that this line would print I set 'foobar' to ''
, because the assignment appears to return nothing.
However - thankfully - this assignment acts as expected, and the code prints I set 'foobar' to 'BAZ!'
. Unfortunately, this feels like a contradiction, because the invoked setter's return value belies the fact that the assignment returns the value assigned to it. At first I figured that mcInst.foobar = @"BAZ!";
is making two calls instead a block: first the setter and then the getter to gather the return value. However, instrumenting the setter and getter methods with NSLog
calls proves this isn't the case.
assign -assign is the default and simply performs a variable assignment -assign is a property attribute that tells the compiler how to synthesize the property's setter implementation -I would use assign for C primitive properties and weak for weak references to Objective-C objects.
Assignment (=)The simple assignment operator ( = ) is used to assign a value to a variable.
The assignment operator = assigns the value of its right-hand operand to a variable, a property, or an indexer element given by its left-hand operand. The result of an assignment expression is the value assigned to the left-hand operand.
Retain increases the retain count of an object by 1 and takes ownership of an object. Whereas copy will copy the data present in the memory location and will assign it to the variable so in the case of copy you are first copying the data from a location assign it to the variable which increases the retain count.
Quick Summary:
The quick answer here is that there is no contradiction, because the result of the expression:
(mcInst.foobar = @"BAZ!")
is actually @"BAZ!"
, and not mcInst.foobar
.
More detail is available below, but it might help to consider the following modification to your setFoobar
method:
- (void) setFoobar:(NSString*)fbSet
{
[_foobar release];
_foobar = [[NSString stringWithFormat:@"HELLO_%@", fbSet] retain];
}
With this code in place, the value of the foobar
property is modified while it is being set, but your line of code will still display the value 'BAZ!'.
Details:
As pointed out by newacct, your NSLog code works because you use the assignment operator (=), which has some very specific behaviour in the C language (which Objective-C is based upon)
In C, you can do the following:
x = y = z = 42;
and all of the variables, x
, y
and z
will hold the value 42.
The compiler handles this behaviour by using a temporary variable(*). Essentially, what happens behind the scenes looks something like this:
tempVar = 42;
z = tempVar;
y = tempVar;
x = tempVar;
Along the same lines, you can do the following:
SomeFunction(x = 42);
this line of code will copy the value of 42 into x, and then call SomeFunction
with an argument of 42. Behind the scenes, it looks like this:
tempVar = 42;
x = tempVar;
SomeFunction(tempVar);
Now, in Objective-C, your logging line is handled as follows:
tempVar = @"BAZ!";
[mcInst setFooBar:tempVar];
NSLog(@"I set 'foobar' to '%@'", tempVar);
(*) note that the usage of a "temporaray variable" I describe is meant to illustrate the concept, and may not actually reflect what any given compiler actually does under the hood. That sort of implementation detail is up to the programmers who write the compiler, and each one may do something different. The end result, however, is the same.
There's no need to call a getter — it has the value being assigned right there on the same line. You can think of it as expanding to [mcInst setFoobar:@"BAZ!"], @"BAZ!"
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With