myView.frame.origin.x = 值;不起作用 - 但为啥?
Posted
技术标签:
【中文标题】myView.frame.origin.x = 值;不起作用 - 但为啥?【英文标题】:myView.frame.origin.x = value; does not work - But why?myView.frame.origin.x = 值;不起作用 - 但为什么? 【发布时间】:2011-02-28 08:32:31 【问题描述】:我知道我不能用这个:
myView.frame.origin.x = 25.0;
我必须改用这个:
CGRect myFrame = myView.frame;
myFrame.origin.x = 25.0;
myView.frame = myFrame;
我一直都在这样做,但我不知道为什么我必须这样做。我想填补我理解的空白。有人可以解释吗?
现在 Xcode 为您提供“表达式不可分配”。前段时间你得到一个编译错误“需要左值作为赋值的左操作数”。
【问题讨论】:
+1 - 我一直在想这个问题...... 【参考方案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
【讨论】:
我认为您应该首先从编译器获得“左值作为赋值的左操作数”。【参考方案2】:A CGRect
是一个结构,它来自标准 C。A CGRect
不是一个 Objective C 对象,所以当你分配给它的一个成员时,没有 setter 方法叫。如果没有调用 setter 方法,UIKit 将无法知道发生了什么变化,因此无法更新屏幕显示。
编辑:正如已经指出的那样,分配将是结构的副本。
【讨论】:
【参考方案3】:这里使用了两种不同的点语法。它们看起来一样,但根据它们的操作和正在执行的操作,它们会做不同的事情:
第一个myView.frame
是[myView frame]
的简写,这是一个返回CGRect
结构的方法调用按值。
myFrame.origin.x
正在以传统 C 方式访问普通结构成员。
第二个myView.frame
又是一个简写,但由于该语句是一个赋值,它转换为调用不同的方法[myView setFrame:myFrame]
。
在您的单行顶部示例中,您获得了 rect 的副本并设置其 x
,但永远不要将其复制回视图。您必须明确区分方法调用,点语法糖不能将它们魔术到单个调用中。
【讨论】:
【参考方案4】:这不起作用的原因是由于混合了两种语法。 首先你有“。”作为调用访问器函数的快捷方式(Objective-C 特性)。 所以
a.b 变成 [a getB]; a.b = 5 变为 [a setB:5];然后是“。”作为直接结构成员访问(纯 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,现在您想为其分配一些东西,问题就来了...
你尝试设置一个struct的一个struct的变量,这没问题,但是没有从UIView指向struct的指针,所以它被复制了。因此,您复制然后设置,然后您期望设置的操作通过初始获取以某种方式转发到 UIView,这就是行不通的。
当然,您可能想知道为什么 Apple 不只是创建一个快捷方式,以便最终将您复制的帧自动重新注入到自动附加的 setFrame 调用中,我想您只需要忍受它的现状。
所以请记住,如果你得到一个指向框架的指针,它会起作用,但你没有,你会得到一个复制的结构。
因此,如果您希望 myView.frame.origin.x = 25.0
能够正常工作,您间接希望您的呼叫会自动翻译成某种[myView setFrame:[myView getFrame:frame].origin.x = 25.0]
。
好吧,我想你可以承认这看起来不对。
另外想象一下,如果你得到一个指向 CGRect 框架的直接指针,你会通过那个指针改变一些东西,那么 UIView 怎么知道它的大小已经改变并且它必须更新自己?另一方面,如果调用了 [myView setFrame:newFrame],则 UIView 可以自行进行所有必要的重新调整。
【讨论】:
以上是关于myView.frame.origin.x = 值;不起作用 - 但为啥?的主要内容,如果未能解决你的问题,请参考以下文章