Lord Zsolt
Lord Zsolt

Reputation: 6557

Why can't access view.center.x / y

I'm just curious why can't you access view.center.x or view.center.y but you can access view.center and change it.

I wanted to write this code:

imgView_.center = scrollView_.center;
if (imgView_.frame.origin.x < 0) 
    imgView_.center = CGPointMake(imgView_.center.x + (imgView_.frame.size.width - self.view.frame.size.width) / 2, imgView_.center.y);
if (imgView_.frame.origin.y < 0)
    imgView_.center = CGPointMake(imgView_.center.x, imgView_.center.y + (imgView_.frame.size.height - self.view.frame.size.height) / 2);

As:

imgView_.center = scrollView_.center;
if (imgView_.frame.origin.x < 0) 
    imgView_.center.x = imgView_.center.x + (imgView_.frame.size.width - self.view.frame.size.width) / 2;
if (imgView_.frame.origin.y < 0)
    imgView_.center.y = imgView_.center.y + (imgView_.frame.size.height - self.view.frame.size.height) / 2;

I find the second way a lot more elegant, but I can't access the x and y, so I thought I'd ask if anyone knows what's Apple's reason for blocking it.

Upvotes: 0

Views: 2598

Answers (3)

CRD
CRD

Reputation: 53000

In the fragment imgView_.center.x the .center is a property access while the .x is a field access. The type of the property is CGPoint, which is a structure type which is passed by value.

If you have a variable of type CGPoint you can directly assign to individual fields, e.g.:

CGPoint myPoint;
myPoint.x = 3;

However when passing a CGPoint value to a function or method you cannot pass just one of it's fields - it makes no sense. E.g. if you have the function:

void doSomething(CGPoint aPoint);

you could pass myPoint:

doSomething(myPoint);

but there is no way to say "just pass the x field" - what would that even mean? The function is expecting a CGPoint, what would passing it one coordinate mean?

When you put the fragment imgView_.center on the left hand side of an assignment you are just using a shorthand for calling a method. E.g.:

imgView_.center = myPoint; <=> [imgView_ setCenter:myPoint];

and just like with the function above there is no way to say "just pass the x field".

The key point is a property access is not a variable access, even though it is often thought of as one, but a function/method call; so you can't assign to the individual fields of a property of structure type.

On the right hand side accessing a field of a property is fine. E.g. on the rhs imgView_.center translates to [imgView_ center] - which returns a CGPoint value, and you can access a field of structure value, so on the rhs imgView_.center.x translates to [imgView_ center].x and all is OK. But note that in both cases (setCenter: and center methods) the methods themselves take/return a complete CGPoint.

HTH.

Upvotes: 2

Amar
Amar

Reputation: 13222

The UIView property center is a CGPoint which is of type struct and not an ObjectiveC class.

Even though writing this

view.center.x = view.center.x +10;

looks similar to

CGPoint center = view.center;
center.x = center.x +10;
view.center = center;

they are different things.

According to the compiler view.center is a method call [view center] and center.x is accessing the public ivar of the struct CGPoint. If you write all of this in a single line

view.center.x = view.center.x +10;

compiler is unable to resolve this and throws an error Expression is not assignable. Reason is view.center.x is further resolved as function call,

objc_msgSend(view, @selector(center))

Now you are trying to modify the return value of a C function as below

objc_msgSend(view, @selector(center)).x = 20 //(Some value on RHS) 

which is not meaningful as the function return value isn't stored anywhere, hence the resulting expression is not assignable.

For more information read through this answer.

Hope that helps!

Upvotes: 2

Suryakant Sharma
Suryakant Sharma

Reputation: 3960

See center property defined in UIView's UIViewGeometry category as below

@property(nonatomic) CGPoint center;

By declaration of center property, we have getter & setter methods for center property. it means we have setter & getter method for structure not for the values inside structure. and Center is a CGPoint structure variable that has two CGFloat value x and y.

that's by we can't set directly x and y values in center property. it is similar to Frame property.

Upvotes: 3

Related Questions