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 = 值;不起作用 - 但为啥?的主要内容,如果未能解决你的问题,请参考以下文章

剔除“异常值”的一般原则是什么?

缺失值(NaN 值)与填充值的重叠图

R语言︱异常值检验离群点分析异常值处理

R语言︱异常值检验离群点分析异常值处理

R语言之缺失值和异常值处理

MySql怎么给列设置默认值 mysql修改默认值