ObjC Properties and C Operators

Given the following property declaration:

@property NSInteger foo; 

How do increment, decrement, and compound assignment self.foo on self.foo ?

As far as I understood, self.foo was just syntactic sugar for real access methods. Thus, self.foo does not have direct access to the NSInteger variable called foo , but rather will call either:

 - (void)setFoo:(NSInteger)foo; 

or

 - (NSInteger)foo; 

However, the following set of code is great, not tagged, compiles, and returns exactly the expected results:

 self.foo = 0; NSLog(@"%d",self.foo); // prints 0 self.foo += 1; NSLog(@"%d",self.foo); // prints 1 self.foo++; NSLog(@"%d",self.foo); // prints 2 ++self.foo; NSLog(@"%d",self.foo); // prints 3 

And I think that it is probably safe to assume that the reduction operators before and after the correction, as well as the other 9 compound statements, will do exactly what you would expect if you would use them directly in the NSInteger variable.

I just don't understand WHY this works if self.foo is really just syntactic sugar for the two methods mentioned above.

If I overwrite the default accessors to include NSLog instructions so that I can see when each of them is called and with what values, I see that getter is called first, then setter is called.

Does this mean that the following:

 self.foo += 1; 

effectively replaced by the following:

 [self setFoo:([self foo] + 1)]; 

during precompilation?


EDIT: So, at build level, is there a difference between self.foo += 1; and self.foo = self.foo + 1; ? What if we are not talking about this property, and bar is just a regular int, at the assembly level there is a difference between bar += 1; and bar = bar + 1; ?

+7
operators increment properties objective-c compound-assignment
source share
1 answer

That's right. Your guess is correct. You can implement the property yourself and add a log to check your assumption again

In the @interface section:

 @property(nonatomic) NSInteger foo; // nonatomic keyword is not really required but // it is better to add it since we will implement // property as nonatomic 

In the @implementation section:

 - (void)setFoo:(NSInteger)foo { _foo = foo; // _foo variable is implicitly generated by compiler NSLog(@"set foo %d", _foo); } - (NSInteger)foo { NSLog(@"get foo %d", _foo); return _foo; } 

Then run

 self.foo = 0; self.foo += 1; 

you should get in the debug window:

 set foo 0 get foo 0 set foo 1 

UPDATE:

  • Re: "At the assembly level, is there a difference between self.foo += 1; and self.foo = self.foo + 1; ;?"

Not. For both [self setFoo:([self foo] + 1)]; will be called.

  • Re: What if we do not talk about this property, and bar is just an ordinary int, at the assembly level there is a difference between bar += 1; and bar = bar + 1; ?

Yes. But only if compile-time optimization is disabled.

bar += 1; faster. It will compile something like this:

 mov eax,dword ptr [bar] inc eax // difference is here! mov dword ptr [bar],eax 

And bar = bar + 1; in:

 mov eax,dword ptr [bar] add eax,1 // difference is here! mov dword ptr [bar],eax 
+6
source share

All Articles