自定义视图中的iOS自动布局修改在调用viewDidAppear之前不起作用

时间:2016-03-24 16:47:32

标签: ios swift autolayout

我有视图控制器(如果有问题,请使用故事板)。控制器内部有自定义视图,让我们称之为AView。该视图在故事板上显示为具有自定义类集的UIView对象。 AView的内容在单独的XIB上,因为我需要这个高度可重用的。这是代码的样子:

class VC: UIViewController {
    @IBOutlet weak var aView: AView!

    override func viewDidLoad() {
        super.viewDidLoad()
        aView.setup(false) //doesn't work
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        aView.setup(false) //doesn't work
    }

    override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        aView.setup(false) //do work but glitches
    }

}

class AView: UIView {

    required init?(coder aDecoder: NSCoder) {
        //init stuff: loading nib, adding view from it
    }

    @IBOutlet weak var someView: UIView! //this view has all constraints which are required and additional rightConstraint which is inactive, for future use
    @IBOutlet var leftConstraint: NSLayoutConstraint!
    @IBOutlet var rightConstraint: NSLayoutConstraint!

    func setup(shouldBeOnLeft: Bool) {
        leftConstraint.active = true
        rightConstraint.active = false
        self.layoutIfNeeded()
    }
}

我需要在显示之前根据一些参数设置此视图。我只从内部修改其内部内容。如果我在aView.setup(shouldBeOnLeft:)viewDidLoad约束中呼叫viewWillAppear,请不要更新或者可能会更新,但我不会看到更改。如果我将它移动到viewDidAppear它可以工作但很明显我看到错误的视图一段时间(设置之前的状态)。

问题是:如何使其按预期工作并且没有视图操作形式的视图控制器,并独立于调用setup方法的方式和位置,除非它在VC&之后或之后#39; s viewDidLoad? VC需要知道的只是用参数调用setup。

2 个答案:

答案 0 :(得分:3)

您应该在viewDidLayoutSubviews()内调用它,此时它已经设置了视图参数,您可以在呈现给用户之前操​​纵视图(因此,没有故障)

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/#//apple_ref/occ/instm/UIViewController/viewDidLayoutSubviews

  

<强>讨论    被调用以通知视图控制器其视图刚刚布置了其子视图。

答案 1 :(得分:0)

好的,我想出来了 - 但我真的不喜欢100%

class VC: UIViewController {
    @IBOutlet weak var aView: AView!

    override func viewDidLoad() {
        super.viewDidLoad()
        aView.setup(false) //now it does work
    }
 }

class AView: UIView {

    required init?(coder aDecoder: NSCoder) {
        //init stuff: loading nib, adding view from it
    }

    @IBOutlet weak var someView: UIView! //this view has all constraints which are required and additional rightConstraint which is inactive, for future use
    @IBOutlet var leftConstraint: NSLayoutConstraint!
    @IBOutlet var rightConstraint: NSLayoutConstraint!

    func setup(shouldBeOnLeft: Bool) {
        self.yesIfLeft = shouldBeOnLeft
    }

    private var yesIfLeft = false {
        didSet{
            self.updateLayout()
        }
    }

    private func updateLayout() {
        leftConstraint.active = self.yesIfLeft
        rightConstraint.active = !self.yesIfLeft
        self.layoutIfNeeded()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        self.updateLayout()
    }
}

重点是保持对引起布局更改的设置的引用,并在layoutSubviews()中更新它们。这样做VC不必知道AView的内部(这对我来说是一个很大的优点),但要求AView保持其配置,这是一些额外的要做的工作。我现在不接受这个答案,因为也许有人会有更好的想法。