myView.frame.origin.x = value;不起作用 - 但为什么?

时间:2010-06-06 10:20:27

标签: objective-c struct variable-assignment declared-property

我知道我不能用这个:

myView.frame.origin.x = 25.0;

我必须改用它:

CGRect myFrame = myView.frame;
myFrame.origin.x = 25.0;
myView.frame = myFrame;

而且我一直这样做,但我不知道为什么我必须这样做。我想在我的理解中填补这个空白。谁能解释一下?

现在Xcode为您提供“Expression not assignable”。前段时间你得到一个编译错误“Lvalue需要作为赋值的左操作数”。

4 个答案:

答案 0 :(得分:40)

这里使用了两种不同的点语法。它们看起来是一样的,但它们根据它们的操作以及使用它做了什么来做不同的事情:

  • 第一个myView.frame[myView frame]的简写,这是一个按值返回CGRect struct 的方法调用。
  • myFrame.origin.x正在以传统的C方式访问普通的struct成员。
  • 第二个myView.frame也是一个简写,但由于该语句是赋值,它转换为调用其他方法[myView setFrame:myFrame]

在单行顶部示例中,您将获得rect的副本并设置其x,但不要将其复制回视图。你必须明确地区分方法调用,点语法糖不能将它们变成单个调用。

答案 1 :(得分:17)

这不起作用的原因是由于两种语法的混合 首先你有“。”作为调用访问器函数的快捷方式(Objective-C功能)。 所以

  • a.b成为[a getB];
  • a.b = 5变为[a setB:5];

然后theres“。”作为直接结构成员访问(纯C)。所以

  • a.b真的是a.b;
  • a.b真的是a.b = 5;

在这样的设定值案例中将其组合起来是行不通的 因为...... 如果你可以打电话

myView.frame.origin.x = 25.0;
  • “myView.frame”部分等于[myView getFrame],你得到一个复制的CGRect框架(一个C结构)

  • “myView.frame.origin”为您提供复制的CGRect的CGPoint原点(也是结构)

  • “myView.frame.origin.x = 25.0”为您提供了原始的CGFloat x,现在您想为其分配一些东西,问题就出现了......

您尝试设置结构的结构的变量,这是正常的,但是没有从UIView到结构的指针,因此它被复制。所以你复制然后你设置然后你期望set动作以某种方式通过初始转到UIView转发,好吧,这只是不起作用。

当然你可能想知道为什么Apple还没有创建一个快捷方式,所以最终你复制的帧会被自动重新注入一个自动附加的setFrame调用,我想你只需要忍受它是如何实现的。

所以请记住,如果你得到一个指向框架的指针,它会起作用,但是你没有,你会得到一个复制的结构。
因此,如果您希望myView.frame.origin.x = 25.0能够工作,则间接期望您的呼叫会自动转换为某种形式 [myView setFrame:[myView getFrame:frame].origin.x = 25.0]
嗯,我想你可以承认这看起来不对。

另外想象一下,如果你得到一个指向CGRect框架的直接指针并且你通过该指针改变某些东西,UIView将如何知道它的大小已经改变并且它必须自己更新?另一方面,如果进行[myView setFrame:newFrame]调用,则UIView可以自行完成所有必要的调整。

答案 2 :(得分:2)

CGRect是一个结构,它来自标准C.A CGRect 是一个Objective C对象,所以当你分配给它的一个成员时,没有调用setter方法。如果没有调用setter方法,UIKit将无法知道任何更改,因此无法更新屏幕显示。

编辑:正如已经指出的那样,赋值将是结构的副本。

答案 3 :(得分:1)

当您直接操作数据时,不会调用任何访问者,因此UI无法自行更新 - 或者通知任何其他想要了解更改的组件。

编辑:正如walkytalky指出的那样,您将获得数据的副本,因此无论如何更改它都不会对原始数据产生任何影响。以下示例将显示:

UIView *aView = [[UIView alloc] initWithFrame:CGRectMake(50,50,100,100)];
NSLog(@"%f", aView.frame.origin.x); // will give 50
aView.frame.origin.x = 17;  // operates on a copy of the rect only
NSLog(@"%f", aView.frame.origin.x);  // will still give 50