31

我知道我不能使用这个:

myView.frame.origin.x = 25.0;

我必须改用这个:

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

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

现在 Xcode 给你“表达不可分配”。前段时间你得到一个编译错误“需要左值作为赋值的左操作数”。

4

4 回答 4

41

这里使用了两种不同的点语法。它们看起来一样,但是根据它们的操作和正在执行的操作,它们会做不同的事情:

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

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

于 2010-06-06T10:56:33.710 回答
17

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

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

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

  • ab 真的是 ab;
  • ab 真的是 ab = 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 指向该结构的指针,所以它被复制了。因此,您复制然后设置,然后您期望设置的操作通过初始获取以某种方式转发到 UIView,好吧,这只是行不通。

当然,您可能想知道为什么 Apple 不只是创建一个快捷方式,以便最终将您复制的帧自动重新注入到自动附加的 setFrame 调用中,我想您只需要忍受它的现状。

所以请记住,如果你得到一个指向框架的指针,它会起作用,但你没有,你会得到一个复制的结构。
因此,如果您希望myView.frame.origin.x = 25.0工作,您间接希望您的呼叫被自动翻译成某种
[myView setFrame:[myView getFrame:frame].origin.x = 25.0].
好吧,我想你可以承认这看起来是错误的。

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

于 2010-06-06T11:18:56.947 回答
2

ACGRect是一个结构,它来自标准 C。ACGRect不是Objective C 对象,因此当您分配给它的一个成员时,不会调用任何 setter 方法如果没有调用 setter 方法,UIKit 将无法知道发生了什么变化,因此无法更新屏幕显示。

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

于 2010-06-06T10:52:52.670 回答
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
于 2010-06-06T10:45:06.263 回答