ios 以编程方式创建视图时,我应该在哪里设置自动布局约束

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19387998/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 02:20:59  来源:igfitidea点击:

Where should I be setting autolayout constraints when creating views programmatically

ioscocoa-touchautolayout

提问by Heisenberg

I see different examples where constraints are set. Some set them in viewDidLoad/ loadView(after the subview was added). Others set them in the method updateViewConstraints, which gets called by viewDidAppear.

我看到设置约束的不同示例。有些将它们设置在viewDidLoad/ loadView(在添加子视图之后)。其他人将它们设置在由updateViewConstraints调用的方法中viewDidAppear

When I try setting constraints in updateViewContraintsthere can be a jumpiness to the layout, e.g. slight delay before the view appears. Also, if I use this method, should I clear out existing constraints first i.e. [self.view [removeConstraints:self.view.constraints]?

当我尝试在updateViewContraints其中设置约束时,布局可能会出现跳跃,例如在视图出现之前会有轻微的延迟。另外,如果我使用这种方法,我应该先清除现有的约束[self.view [removeConstraints:self.view.constraints]吗?

回答by Arek Holko

I set up my constraints in viewDidLoad/loadView(I'm targeting iOS >= 6). updateViewConstraintsis useful for changing values of constraints, e.g. if some constraint is dependent on the orientation of the screen (I know, it's a bad practice) you can change its constantin this method.

我在viewDidLoad/ 中设置了我的约束loadView(我的目标是 iOS >= 6)。updateViewConstraints对于更改约束的值很有用,例如,如果某些约束依赖于屏幕的方向(我知道,这是一种不好的做法),您可以constant在此方法中更改它。

Adding constraints in viewDidLoadis showed during the session "Introduction to Auto Layout for iOS and OS X"(WWDC 2012), starting from 39:22. I think it's one of those things that are said during lectures but don't land in the documentation.

viewDidLoad在会议“iOS 和 OS X 的自动布局简介”(WWDC 2012)中,从 39:22 开始,显示了添加约束。我认为这是在讲座中说过但没有出现在文档中的事情之一。

UPDATE:I've noticed the mention of setting up constraints in Resource Management in View Controllers:

更新:我注意到在视图控制器中的资源管理中提到了设置约束:

If you prefer to create views programmatically, instead of using a storyboard, you do so by overriding your view controller's loadViewmethod. Your implementation of this method should do the following:

(...)

3.If you are using auto layout, assign sufficient constraints to each of the views you just created to control the position and size of your views. Otherwise, implement the viewWillLayoutSubviewsand viewDidLayoutSubviewsmethods to adjust the frames of the subviews in the view hierarchy. See “Resizing the View Controller's Views.”

如果您更喜欢以编程方式创建视图,而不是使用故事板,您可以通过覆盖视图控制器的loadView方法来实现。此方法的实现应执行以下操作:

(……)

3.如果您使用自动布局,请为您刚刚创建的每个视图分配足够的约束以控制您的视图的位置和大小。否则,实现viewWillLayoutSubviewsviewDidLayoutSubviews方法来调整视图层次结构中子视图的框架。请参阅“调整视图控制器视图的大小”。

UPDATE 2: During WWDC 2015 Apple gave a new explanationof updateConstraintsand updateViewConstraintsrecommended usage:

更新2:2015年WWDC期间苹果给予了新的解释updateConstraintsupdateViewConstraints推荐的用法:

Really, all this is is a way for views to have a chance to make changes to constraints just in time for the next layout pass, but it's often not actually needed.

All of your initial constraint setup should ideally happen inside Interface Builder.

Or if you really find that you need to allocate your constraints programmatically, some place like viewDidLoad is much better.

Update constraints is really just for work that needs to be repeated periodically.

Also, it's pretty straightforward to just change constraints when you find the need to do that; whereas, if you take that logic apart from the other code that's related to it and you move it into a separate method that gets executed at a later time, your code becomes a lot harder to follow, so it will be harder for you to maintain, it will be a lot harder for other people to understand.

So when would you need to use update constraints?

Well, it boils down to performance.

If you find that just changing your constraints in place is too slow, then update constraints might be able to help you out.

It turns out that changing a constraint inside update constraints is actually faster than changing a constraint at other times.

The reason for that is because the engine is able to treat all the constraint changes that happen in this pass as a batch.

实际上,所有这些都是视图有机会在下一次布局传递时及时更改约束的一种方式,但实际上通常不需要它。

理想情况下,所有初始约束设置都应在 Interface Builder 中进行。

或者如果你真的发现你需要以编程方式分配你的约束,像 viewDidLoad 这样的地方会好得多。

更新约束实际上仅适用于需要定期重复的工作。

此外,当您发现需要这样做时,更改约束非常简单;然而,如果您将该逻辑与与其相关的其他代码分开,并将其移动到稍后执行的单独方法中,您的代码将变得更加难以遵循,因此您将更难维护,其他人会很难理解。

那么什么时候需要使用更新约束呢?

好吧,这归结为性能。

如果您发现仅就地更改约束太慢,那么更新约束可能会帮助您解决问题。

事实证明,在更新约束内更改约束实际上比在其他时间更改约束更快。

这样做的原因是因为引擎能够将在此传递中发生的所有约束更改视为批处理。

回答by BooRanger

I recommend creating a BOOL and setting them in the -updateConstraintsof UIView (or -updateViewConstraints, for UIViewController).

我建议创建一个 BOOL 并将它们设置在-updateConstraintsUIView 中(或者-updateViewConstraints,对于 UIViewController)。

-[UIView updateConstraints]: (apple docs)

-[UIView updateConstraints]:(苹果文档)

Custom views that set up constraints themselves should do so by overriding this method.

自己设置约束的自定义视图应该通过覆盖此方法来实现。

Both -updateConstraintsand -updateViewConstraintsmay be called multiple times during a view's lifetime. (Calling setNeedsUpdateConstraintson a view will trigger this to happen, for example.) As a result, you need to make sure to prevent creating and activating duplicate constraints -- either using a BOOL to only perform certain constraint setup only once, or by making sure to deactivate/remove existing constraints before creating & activating new ones.

双方-updateConstraints-updateViewConstraints可能视图的一生中多次调用。(例如,调用setNeedsUpdateConstraints视图会触发这种情况。)因此,您需要确保防止创建和激活重复的约束——要么使用 BOOL 只执行一次特定的约束设置,要么确保在创建和激活新约束之前停用/删除现有约束。

For example:

例如:

  - (void)updateConstraints {  // for view controllers, use -updateViewConstraints

         if (!_hasLoadedConstraints) {
              _hasLoadedConstraints = YES;
             // create your constraints
         }
         [super updateConstraints];
    }

Cheers to @fresidue in the comments for pointing out that Apple's docs recommend calling superas the last step. If you call superbefore making changes to some constraints, you may hit a runtime exception (crash).

在评论中为 @fresidue 干杯,指出 Apple 的文档建议将调用super作为最后一步。如果super在更改某些约束之前调用,则可能会遇到运行时异常(崩溃)。

回答by BluelineCoding

This should be done in ViewDidLoad, as per WWDC video from Apple and the documentation.

根据 Apple 的 WWDC 视频和文档,这应该在 ViewDidLoad 中完成。

No idea why people recommend updateConstraints. If you do in updateConstraints you will hit issues with NSAutoresizingMaskLayoutConstraint with auto resizing because your views have already taken into account the auto masks. You would need to remove them in updateConstraints to make work.

不知道为什么人们推荐 updateConstraints。如果您在 updateConstraints 中这样做,您将遇到 NSAutoresizingMaskLayoutConstraint 自动调整大小的问题,因为您的视图已经考虑了自动掩码。您需要在 updateConstraints 中删除它们才能工作。

UpdateConstraints should be for just that, when you need to 'update' them, make changes etc from your initial setup.

UpdateConstraints 应该就是这样,当您需要“更新”它们时,从初始设置中进行更改等。

回答by Kit

Do it in view did layout subviews method

在视图中执行布局子视图方法

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
}

回答by Davide

I have this solution to change constraints before those who are in the storyboard are loaded. This solution removes any lags after the view is loaded.

我有这个解决方案可以在加载故事板中的约束之前更改约束。此解决方案消除了加载视图后的任何滞后。

-(void)updateViewConstraints{

    dispatch_async(dispatch_get_main_queue(), ^{

            //Modify here your Constraint -> Activate the new constraint and deactivate the old one

            self.yourContraintA.active = true;
            self.yourContraintB.active= false;
            //ecc..
           });

    [super updateViewConstraints]; // This must be the last thing that you do here -> if! ->Crash!
}

回答by Andre Simon

You can set them in viewWillLayoutSubviews:too:

您也可以在viewWillLayoutSubviews 中设置它们:

 override func viewWillLayoutSubviews() {

    if(!wasViewLoaded){
        wasViewLoaded = true

        //update constraint

        //also maybe add a subview            
    }
}

回答by Michele Dall'Agata

This worked for me:

这对我有用:

Swift 4.2

斯威夫特 4.2

override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

// Modify your constraints in here

  ...

}

Although honestly I am not sure if it is worth it. It seems a bit slower to load than in viewDidLoad(). I just wanted to move them out of the latter, because it's getting massive.

虽然老实说我不确定这是否值得。加载似乎比 viewDidLoad() 慢一点。我只是想将它们从后者中移出,因为它变得越来越庞大。