views:

1398

answers:

3

In the following code:

_imageView.hasHorizontalScroller = YES;
_imageView.hasVerticalScroller = YES;
_imageView.autohidesScrollers = YES;

NSLog(@"scrollbar? H %p V %p hide %p", 
      &(_imageView.hasHorizontalScroller), 
      &(_imageView.hasVerticalScroller),
      &(_imageView.autohidesScrollers));

I'm getting the error:

Controller.m:143: error: lvalue required as unary '&' operand
Controller.m:144: error: lvalue required as unary '&' operand
Controller.m:145: error: lvalue required as unary '&' operand

Notice that I am USING those variables as lvalues directly before the & lines...

How can it complain that a value isn't an lvalue right after I assign to it with no error? does this have to do with the magical getters/setters that objective C creates?

I think I need to explain some context to explain WHY I'm trying to get the address:

in my previous SO post, I showed the same code, printing %d and finding that after the assignments, the properties were still 0 for some reason. So, I figured I'd try to get the addresses of the properties to see where they're being stored and maybe I can figure out why I'm not successfully assigning to them, and then this happened.

I think that as people have mentioned, yeah, it's probably that when I do the assigment obj-c is secretly replacing that with a call to the setter (and then some other magic because in another SO post, someone else mentioned that

BOOL b = [_imageView setHasVerticleScroller: YES]

fails, but

BOOL b = _imageView.hasVerticalScroller = YES;

works fine.

+2  A: 

I'm not 100% sure, but I'm going to take a stab at the answer.

Those properties are all BOOL types, which is (I believe) an unsigned char in Objective-C. (Maybe an int, I can't remember, but it's something like that.) So you're trying to take the address of (&) those properties. But you're not actually accessing the ivars directly; properties go through a method call to get their values. So you're trying to get the address of the BOOL return value of a method, but since you're not actually assigning the value to anything, there is no address -- you just have the value.

You'd have the same problem if you did this:

static int returnOne(void)
{
    return 1;
}

// Later...

NSLog(@"returnOne is %p", &returnOne());    // Oops, the return value of returnOne has no address!

Your log call should look like this:

NSLog(@"scrollbar? H %d V %d hide %d", 
  _imageView.hasHorizontalScroller, 
  _imageView.hasVerticalScroller,
  _imageView.autohidesScrollers);
mipadi
my log call isn't actually trying to show the VALUES. I want the locations, as a debugging step... I already know the values are all 0, and I'm trying to figure out why...
Brian Postow
Right, but the point is, the values don't have an address -- they have no location -- since they're just being returned from a method call and aren't being assigned. Properties are actually *method calls* -- you're not accessing the variable itself.
mipadi
Well, that raises the question of why chained assignments work... but that may be another special case...
Brian Postow
You mean, something like `obj.property.anotherProperty = otherObj`? That is basically the same as `[[obj property] setAnotherProperty:otherObj]`; you're not taking the address of at any point, so there's no reason it shouldn't work.
mipadi
No, I mean BOOL b = _imageView.hasHorizontalScroller = YES;DOES in fact work. however, since the setter returns void, b = [_imageView setHasHorizontalScroller: YES]; does NOT work.
Brian Postow
That's because `BOOL b = _imageView.hasHorizontalScroller = YES` is probably equivalent to something like `[_imageView hasHorizontalScroller:YES]; BOOL b = [_imageView horizontalScroller]`.
mipadi
something like it, but not that exactly because the problem I'm ACTUALLY trying to solve is figure out why the horizontal scroller setter isn't working. After this statement, [_imageView hasHorizontalScroller] returns 0, which is my fundamental problem...
Brian Postow
mipadi
Now I'm confused. ignoring the dots and the NSLog(@"horizontal %d", [_imageView hasHorizontalScroller]); prints out horizontal 0. My fundamental problem is that I'm trying to figure outwhy...
Brian Postow
+2  A: 

_imageView.hasHorizontalScroller = YES; - in this line you access property in imageView - so you do not actually access value, but call setter method:

[_imageView  setHasHorizontalScroller:YES]; // Equivalent of your code.

In second example you also access property, but this time getter method gets called and returns BOOL. So as mipadi points you do not need to use & in that NSLog statement.

I'd suggest to read docs about properties in obj-c.

Edit: here you can find the discussion about why properties work in multiple assignment statements like you mentioned:

BOOL b = _imageView.hasVerticalScroller = YES;
Vladimir
so, basically you're saying "Yes, it's the magical getters/setters" ...
Brian Postow
basically, yes :)
Vladimir
A: 

A similar question when trying to access further into structs.

epatel