在Swift

时间:2017-06-14 19:19:55

标签: swift3 uiscrollview xcode8

我有一种情况,我正在使用UIScrollView来帮助使用较小手机的用户查看窗口内的全文。我想要显示一个图像图标,如果他们需要滚动(只是为了让他们知道窗口内有更多内容)但是我在使用Swift查找scrollview的高度时遇到了问题。

这是我的对象的层次结构

enter image description here

基本上,这4个标签适合4.7“iPhone而不是4”iPhone。我尝试设置一些逻辑来检查UIScrollView内容是否大于窗口,但它似乎没有工作。我一直认为高度为零。

我正在使用scrollHeight = scrollView.contentSize.height并尝试将其置于viewDidLoad()viewWillAppear()viewDidLayoutSubviews()内,但每次最终都为0。

contentSize我应该用它来检查身高吗?

1 个答案:

答案 0 :(得分:8)

<强> TL; DR;

作为一般指南,自动布局无法在调用viewDidLoad时完成视图的大小(在viewDidLayoutSubviews内也不正确)。要在查询boundsframe之前确保所有观看次数及其子视图的尺寸正确,请执行以下操作:

self.view.setNeedsLayout()
self.view.layoutIfNeeded()
print(self.someSubview.frame) // gives correct frame

<强>解释

有点违反直觉,将代码放在viewDidLayoutSubviews中并不意味着所有子视图都通过自动布局给出了正确的大小。引用the docs for this method

  

但是,调用此方法并不表示已调整视图子视图的各个布局。

这意味着:在viewDidLayoutSubviews内,只有第一层次的子视图具有正确的大小(即子视图,但不是#34;孙视图和#34;)。

这是我创建的示例布局(红色视图是子视图,蓝色视图是孙视图)。

关于这个例子的一些要点:

  • 所有视图都使用自动布局约束定位到其父视图(固定边距,但不是固定宽度),这允许它们增长或缩小,具体取决于我运行此模拟器的屏幕大小上。
  • 我在故事板中使用了iPhone 7大小的视图控制器,并在iPhone 7 Plus模拟器上运行了该示例。这意味着我可以确定视图会有所增长,并使用它来确定视图是否具有原始大小或最终大小。

请注意,在Interface Builder中,子视图的原始宽度(红色)为240磅,孙子视图的原始宽度(蓝色)为200磅。

demo

以下是代码:

class ViewController: UIViewController {

    @IBOutlet weak var childView: UIView!
    @IBOutlet weak var grandchildView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        print("child     ", #function, childView.frame.size.width)
        print("grandchild", #function, grandchildView.frame.size.width)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        print("child     ", #function, childView.frame.size.width)
        print("grandchild", #function, grandchildView.frame.size.width)
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        print("child     ", #function, childView.frame.size.width)
        print("grandchild", #function, grandchildView.frame.size.width)
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print("child     ", #function, childView.frame.size.width)
        print("grandchild", #function, grandchildView.frame.size.width)
    }
}

这是输出:

child      viewDidLoad() 240.0
grandchild viewDidLoad() 200.0
child      viewWillAppear 240.0
grandchild viewWillAppear 200.0
child      viewDidLayoutSubviews() 271.0 // `child` has it's final width now
grandchild viewDidLayoutSubviews() 200.0 // `grandchild` still has it's original width!

// By now, in MOST cases, all views will have their correct sizes.
child      viewDidAppear 271.0
grandchild viewDidAppear 231.0

您可以从此输出中看到,viewDidLayoutSubviews 保证通过View Controller的主视图的直接子视图的任何内容都具有正确的大小。

注意:通常在调用viewDidAppear时,视图的大小正确,但我说这无法保证