2010-06-06 47 views
31

我知道,我不能使用此:myView.frame.origin.x = value;不起作用 - 但是为什么?

myView.frame.origin.x = 25.0; 

而且我不得不改用此:

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

而且我做这一切的时候,但我不知道为什么我必须这样做。我想填补我的理解空白。有人可以解释吗?

如今Xcode给你“Expression not assignable”。前一段时间,你得到一个编译错误“左值作为赋值的左操作数”。

+1

+1 - 我一直在想这个问题已经有一段时间了.. – Emil 2010-06-06 10:33:28

回答

17

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

  • a.b变成[a getB];
  • a.b = 5变成[a集合B:5];

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

  • AB真的是AB;
  • AB真的是AB = 5;

在设定值情况下的这样这个组合,不能正常工作。
因为...... 如果你能打电话

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

  • 的“myView.frame.origin”给你的一个CGPoint原点(也有结构)复制的CGRect

  • 的“myView.frame.origin.x = 25.0”给你一个CGFloat的原点的x,现在你要分配的东西它和这里来的问题......

您尝试设置结构的结构变量,这没问题,但是没有从UIView指向结构的指针,因此它被复制。所以你复制,然后你设置,然后你期望设置的行动是通过初始获取转到UIView,好吧,这是行不通的。

当然,你可能想知道为什么苹果公司并没有创建一个快捷方式,所以最终你的复制框架会自动重新注入到一个自动附加的setFrame调用中,我想你只能忍受它是如何生活的。

所以记住,如果你得到一个指向帧的指针,但你不知道,你会得到一个复制的结构。
因此,如果你期望myView.frame.origin.x = 25.0工作,你间接期望你的电话被自动翻译成某种
[myView setFrame:[myView getFrame:frame].origin.x = 25.0]
嗯,我想你可以承认这看起来不对。

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

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 
+0

我认为你应该得到一个 “作为编译器左边操作数所需的左值首先来自编译器” “。 – Allisone 2010-06-06 12:34:25

+0

它仍然让我了解。谢谢 – Allisone 2010-06-06 12:51:59

+0

这里没有编译警告... – Eiko 2010-06-06 13:04:52

2

CGRect是一个结构,它是由标准C.甲CGRect东西是不一个目标C对象,所以当分配给它的一个成员,没有setter方法被调用。如果没有调用setter方法,UIKit将无法知道任何内容已更改,因此无法更新屏幕显示。

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

39

这里使用了两种截然不同的点语法。他们看起来是一样的,但他们确实取决于他们所操作的,什么是正在用它做不同的事情:

  • 第一myView.frame[myView frame]的简写,即通过返回CGRect结构方法调用值
  • myFrame.origin.x正以传统的C风格访问普通的struct成员。
  • 第二个myView.frame又是一个简写,但因为该语句是分配它转换为调用不同的方法,[myView setFrame:myFrame]

在您的单行顶部例如,你得到的矩形的副本,并设置其x,但从来没有回复制到视图。您必须明确区分方法调用,点语法糖不能将它们魔术化为单个调用。

+2

很好的解释! – reflog 2010-06-06 11:02:38

相关问题