Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-C property assignment returns the assigned value?

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.

like image 692
rpj Avatar asked Jan 13 '10 21:01

rpj


People also ask

What is assign property in Objective C?

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.

Which operator is used to assign value to a variable?

Assignment (=)The simple assignment operator ( = ) is used to assign a value to a variable.

What is the function of assignment operator?

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.

What is copy and retain and in IOS?

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.


2 Answers

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.

like image 121
e.James Avatar answered Nov 29 '22 21:11

e.James


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!".

like image 42
Chuck Avatar answered Nov 29 '22 22:11

Chuck