Ios 为什么重复使用CGRect来重新定位视图是不好的?

Ios 为什么重复使用CGRect来重新定位视图是不好的?,ios,Ios,在我的项目中,我有大量视图,在这些视图中,我对子视图进行程序性的重新调整大小和位置。我在layoutSubviews中使用如下代码执行此操作: CGRect rect = self.btnOne.frame; // change values for rect self.btnOne.frame = rect; // re-use same CGRect to reposition other views rect = self.btnTwo.frame; // change values s

在我的项目中,我有大量视图,在这些视图中,我对子视图进行程序性的重新调整大小和位置。我在
layoutSubviews
中使用如下代码执行此操作:

CGRect rect = self.btnOne.frame;
// change values for rect
self.btnOne.frame = rect;

// re-use same CGRect to reposition other views
rect = self.btnTwo.frame;
// change values
self.btnTwo.frame = rect;

// etc. ...
几年来,这种代码一直对我很好。我最近在一个同事的项目中添加了一堆这样的代码,现在它的行为开始变得非常奇怪。不知什么原因,我想不出,现在这里重复使用的
rect
对象有时会在为其指定视图的帧和在块末尾重新指定视图的帧之间随机更改其自身的值。结果是子视图的位置不正确。似乎错误的形式通常是
rect.origin.x
以某种方式获取
rect.origin.y
的值,反之亦然

更奇怪的是,这个问题只发生在真正的设备上;在模拟器上运行的完全相同的代码没有问题

修复方法是为每个子视图使用唯一声明的CGRect对象,如下所示:

CGRect rect = self.btnOne.frame;
// change values for rect
self.btnOne.frame = rect;

// declare new CGRect to reposition other views
CGRect rect2 = self.btnTwo.frame;
// change values
self.btnTwo.frame = rect2;
当我做出这个改变时,一切都恢复正常。但是我真的很想知道为什么会发生这种情况,特别是为什么会发生在设备上而不是模拟器上。在同事对视图进行更改之前,这种情况似乎也不会发生,尽管我不清楚任何更改(与视图定位无关)是如何做到这一点的


另一个变化是,导入代码的项目使用的是ARC,而我的原始代码不是。

如果真的没有其他事情发生,听起来像是编译器错误。CGRECT没有什么神奇之处。它们只是结构

有优化和没有优化的结果相同吗?在不同的编译器上(gcc llvm vs clang,gcc,如果您还有它的话)

这些都在armv7设备上吗?armv6设备上的thumb代码存在已知问题,并且在过去没有被禁用。从Xcode 4.3开始,苹果似乎想关闭所有Arch的thumb

如果代码像您展示的那样简单,那么查看程序集应该不会那么困难


我一直在重复使用CGRECT。

如果真的没有其他事情发生,那听起来像是编译器错误。CGRECT没有什么神奇之处。它们只是结构

有优化和没有优化的结果相同吗?在不同的编译器上(gcc llvm vs clang,gcc,如果您还有它的话)

这些都在armv7设备上吗?armv6设备上的thumb代码存在已知问题,并且在过去没有被禁用。从Xcode 4.3开始,苹果似乎想关闭所有Arch的thumb

如果代码像您展示的那样简单,那么查看程序集应该不会那么困难


我一直重复使用CGRECT。

self.btnOne.frame
没有效果(应该会给您一个编译器警告)。这是您真正的代码吗?因为rect在堆栈上,如果堆栈上的其他位置有一个数组,那么如果某些代码写入数组(或其他结构)的末尾(或开头之前),它可能会覆盖rect的某些部分。您可以在变量上放置一个观察点,并查看它在何处更改,以准确地找出导致它更改的原因。您能否告诉我们您的同事项目中的视图是否受到转换的影响?Apple docs对transform属性发出警告:“如果此属性不是identity transform,则frame属性的值未定义,因此应忽略。”@rob:typo-我忘记添加
=rect编辑…@user1118321:这也许可以解释为什么这个代码工作得很好,直到有人添加了其他东西
没有效果(应该会给您一个编译器警告)。这是您真正的代码吗?因为rect在堆栈上,如果堆栈上的其他位置有一个数组,那么如果某些代码写入数组(或其他结构)的末尾(或开头之前),它可能会覆盖rect的某些部分。您可以在变量上放置一个观察点,并查看它在何处更改,以准确地找出导致它更改的原因。您能否告诉我们您的同事项目中的视图是否受到转换的影响?Apple docs对transform属性发出警告:“如果此属性不是identity transform,则frame属性的值未定义,因此应忽略。”@rob:typo-我忘记添加
=rect编辑…@user1118321:这也许可以解释为什么这段代码工作得很好,直到有人添加了其他东西。代码并不复杂(只是计算CGRect属性的逻辑),但不幸的是,我不会说汇编。我在上面看到的设备都是armv7设备(不了解arm6设备,因为我们目前还没有配置为部署到这些设备上-原始代码都是用armv6 iPod编写的,并且在那里一直工作得很好)。这个问题在模拟器上根本不会发生,这可能是由不同的处理器体系结构造成的。代码并不复杂(只是计算CGRect属性的逻辑),但不幸的是,我不说汇编。我在上面看到的设备都是armv7设备(不知道arm6设备,因为我们目前还没有配置为部署到这些设备上-原始代码都是用armv6 iPod编写的,并且在那里一直运行良好).这个问题在模拟器上根本不会发生,这可能是由不同的处理器体系结构造成的。