iOS AutoLayout - 获取帧大小宽度

use*_*037 58 nslog ios autolayout

我正在使用iOS 6自动布局进行开发

我想记录一条显示视图框宽的消息.

我可以在屏幕上看到textView.

但我得到的宽度和高度为零,我错过了什么?

NSLog(@"textView    = %p", self.textView);
NSLog(@"height      = %f", self.textView.frame.size.height);
NSLog(@"width       = %f", self.textView.frame.size.width);

textView    = 0x882de00
height      = 0.000000
width       = 0.000000
Run Code Online (Sandbox Code Playgroud)

dre*_*zor 154

实际上,上面的答案并不完全正确.我跟着他们,一次又一次地得到了零.

诀窍是将依赖于帧的代码放在viewDidLayoutSubviews方法中

通知视图控制器其视图刚刚布置了其子视图.

不要忘记这个方法被多次调用,并且不是ViewController生命周期的一部分,所以在使用它时要小心.

希望它对某人有所帮助.

只是想补充一点,对于没有横向模式的我的程序,不使用自动布局更简单......我试过,虽然= D

  • 根据经验,这是autolayout工作后最早的回调.我建议使用,例如,一个BOOL来捕获第一次调用它并执行帧依赖逻辑.它不是很优雅,但是在完成特定自动布局约束的回调之前完成工作. (10认同)
  • @dreamzor,我怎么知道它是否是最后一个viewDidLayoutSubviews?我在iOS 7上发现,在viewDidAppear之前只会调用一个viewDidLayoutSubviews,但在iOS 8上,我在viewDidAppear之前看到多个viewDidLayoutSubviews.这很烦人,因为第一个viewDidLayoutSubviews会在iOS 8上给出错误的帧大小,所以我必须首先忽略它 (3认同)

Jes*_*per 56

我认为在你调用它时,自动布局没有时间来布局你的视图.viewDidLoad调用时没有发生自动布局,因为它是在加载视图之后调用的,并且仅在此之后将视图放置到视图控制器的视图层次结构中并最终布局(在视图的layoutSubviews方法中).

编辑:这个答案指出了为什么问题中的场景不起作用.@ dreamzor的答案指出了在哪里放置代码以解决它.


use*_*037 30

  • 将代码放入 viewDidAppear

原因

  • viewDidLoad在autolayout完成之前发生.因此,尚未通过xib中指定的autolayout设置位置
  • viewDidAppear 自动布局完成后发生.

  • 在iOS 6中,基于我的测试,我在第二个控制器中使用了导航控制器,在`viewDidAppear`之前调用了`viewDidLayoutSubviews`,但是在`viewDidLayoutSubviews`中,子视图的帧宽仍然为零.仅在`viewDidAppear`中,子视图的帧宽似乎具有正确的值. (5认同)

小智 30

包含在viewDidLoad()中

self.view.setNeedsLayout()
self.view.layoutIfNeeded()
Run Code Online (Sandbox Code Playgroud)

在访问yourview.frame.size.width之前


Fra*_*scu 13

实际上我设法在我的代码之前强制布局更新viewDidLoad:

override func viewDidLoad() {
        super.viewDidLoad()

        println("bounds before \(self.previewContainer.bounds)");
        //on iPhone 6 plus -> prints bounds before (0.0,0.0,320.0,320.0)

        self.view.setNeedsLayout()
        self.view.layoutIfNeeded()

        println("bounds after \(self.previewContainer.bounds)");
        //on iPhone 6 plus -> prints bounds after (0.0,0.0,414.0,414.0)

        //Size dependent code works here
        self.create()
    }
Run Code Online (Sandbox Code Playgroud)

更新:这似乎不再起作用了


Sam*_*Sol 10

这真是一个奇怪的功能.但我发现:

如果您想在不使用layoutsubviews方法的情况下获取帧,请使用以下方法:

dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"View frame: %@", NSStringFromCGRect(view.frame));
    });
Run Code Online (Sandbox Code Playgroud)

这真奇怪!!!


Ech*_*lon 7

上面的答案都没有完全适用于我,除了viewDidLoad但是它的副作用是在视图动画显示之前不显示我想要的内容,看起来很糟糕.

viewDidLayoutSubviews 应该是运行依赖于autolayout完成的代码的正确位置,但正如其他人指出的那样,在最近的iOS版本中它被多次调用,你不知道哪个是最后的调用.

所以我用一个小黑客解决了这个问题.在我的故事板中,mySubview应该小于它的含量self.view.但是当viewDidLayoutSubviews第一次调用时,mySubview仍然有600的宽度,而self.view似乎设置正确(这是一个iPhone项目).所以我要做的就是监视后续调用并检查相对宽度.一旦mySubview小于self.view我可以确定它已经正确布局.

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if self.mySubview.bounds.size.width < self.view.bounds.size.width {

        // mySubview's width became less than the view's width, so it is
        // safe to assume it is now laid out correctly...

    }
}
Run Code Online (Sandbox Code Playgroud)

这样做的好处是不依赖于硬编码的数字,因此它可以适用于所有iPhone外形尺寸.当然,它可能不是所有情况下或所有设备上的灵丹妙药,但可能有许多巧妙的方法来进行相对大小的类似检查.

不,我们不应该这样做,但是直到Apple给我们一些更可靠的回调,我们都会坚持下去.