无法更新viewDidLoad中的view.layer.frame?

dot*_*der 12 uiviewcontroller uiview ios

我试图在我的单一视图控制器项目的viewDidLoad方法中执行以下代码:

self.view.layer.frame = CGRectInset(self.view.layer.frame, 20, 20); 
Run Code Online (Sandbox Code Playgroud)

但它没有给出理想的插图.但是,我在同一方法中进行的其他UI更改确实有效

self.view.layer.backgroundColor = [UIColor orangeColor].CGColor;
Run Code Online (Sandbox Code Playgroud)

上面的代码行工作,背景变为橙色,但框架没有.

只有在viewDidAppear中放置代码行时,插图才有效.如果有人能解释的话,我想了解这种行为的关键原因.先感谢您.

Fré*_*dda 21

我认为你遇到这个问题的问题:

self.view.layer.frame = CGRectInset(self.view.layer.frame, 20, 20);
Run Code Online (Sandbox Code Playgroud)

可以解释如下:

  • 在viewDidLoad中,设置了属性,但尚未定义视图的框架.
  • 在触发viewWillAppear时,它们将被设置.这就解释了为什么那行代码在那里工作.
  • 但是从iOS 5开始,还有一个在viewDidLoad之后和viewWillAppear之前调用的方法,其中设置了视图框架:viewDidLayoutSubviews.

您可以在本季的斯坦福CS193P课程中找到关于iOS编程的完整解释(顺便说一下非常酷).

因此,如果您希望它只工作一次,请使用:

- (void)viewDidLayoutSubviews
{
    self.view.layer.frame = CGRectInset(self.view.layer.frame, 20, 20);
}
Run Code Online (Sandbox Code Playgroud)

PS:我也在Ray的论坛上发布了这个答案.问候,弗雷德


rob*_*off 14

viewDidLoad方法设置视图的帧太早,因为其他东西后来正在更改帧.

例如,如果这是您的根视图控制器,则UIWindow对象将在将视图作为子视图添加到自身时设置视图的框架.在任何外部对象(如)可以获取视图之前,该viewDidLoad方法会在loadView返回后立即运行UIWindow.

您可以使用自定义视图(如果尚未使用)并覆盖setFrame:自定义视图类来测试:

- (void)setFrame:(CGRect)frame {
    [super setFrame:frame];
}
Run Code Online (Sandbox Code Playgroud)

在该方法中放置一个断点,你会看到视图的框架在viewDidLoad返回后的某个时间被设置.

  • 系统在布局阶段之前发送`viewWillAppear`,因此您还没有更新的框架.您需要在布局阶段更新帧,可以在自定义视图类的`layoutSubviews`方法中,也可以在`UIViewController`子类的`viewDidLayoutSubviews`方法中更新. (2认同)

mat*_*att 5

Rob Mayoff的答案是正确和优秀的,但是它的方式略有不同:viewDidLoad只表示视图已加载,即视图控制器已获得其视图.这并不意味着视图已放置在界面中.事实上,这viewDidAppear:确实意味着什么 - 这就是为什么当你在那里运行代码时它起作用的原因.

在这种情况下,你想要初始化关于视图的东西的诀窍是要做得足够晚但只做一次.viewDidAppear:可以在以后轻松再次调用,但您不想再次初始化视图(除非它已被卸载).在iOS 5中,isMovingToParentViewController您可以区分您正在寻找的特定环境.在此之前,可能需要设置BOOL标志,以便仅执行一次最终初始化.

当应用程序启动到横向时会发生相关的陷阱.这里也是太快了,viewDidLoad因为界面还没有旋转到景观中.

但是,这个问题根本不应该出现.插入视图控制器的视图应该是您的业务.视图是根视图控制器,在这种情况下,它的大小是自动正确处理的,或者它是父视图控制器的子节点,在这种情况下,它是父视图控制器调整视图大小的工作(如UINavigationController,例如,已经这样做了,或者视图将以模态方式呈现,在这种情况下,它的大小将自动设置以匹配它所替换的视图.所以我建议你提出一个问题,表明你做错了什么.