ios10:viewDidLoad 框架宽度/高度未正确初始化 [英] ios10: viewDidLoad frame width/height not initialized correctly

查看:37
本文介绍了ios10:viewDidLoad 框架宽度/高度未正确初始化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

自从升级到 XCode8 GM 和 ios10 后,我通过 Interface Builder 创建的所有视图都没有正确初始化,直到远远晚于预期.这意味着在 viewDidLoad、cellForRowAtIndexPath、viewWillAppear 等中,每个视图的帧大小都设置为 {1000,1000}.在某些时候,他们似乎纠正了,但为时已晚.

Since upgrading to XCode8 GM and ios10, all of my views created via Interface Builder are not being initialized correctly until much much later than expected. This means in viewDidLoad, cellForRowAtIndexPath, viewWillAppear, etc, the frame size is set to {1000,1000} for every view. At some point they seem to correct, but its far too late.

遇到的第一个问题是常见的圆角倒圆失败:

The first problem encountered is with common rounding of corners failing across the board:

view.layer.cornerRadius = view.frame.size.width/2

对于依赖帧大小在代码中进行计算的任何事物,都会出现更多问题.

Further problems are showing for anything that relies on frame size to do calculations in the code.

cellForRowAtIndexPath 

对于 cellForRowAtIndexPath,帧大小在初始表格显示时失败,但一旦滚动它就可以正常工作.willDisplayCell:forRowAtIndexPath 也没有正确的帧大小.

For cellForRowAtIndexPath, frame size fails on initial table display, but then works fine once you scroll it. willDisplayCell:forRowAtIndexPath does not have the correct frame size either.

我已经硬编码了一些值,但显然这是非常糟糕的代码实践,在我的项目中也是如此.

I've hardcoded a few values but obviously this is very bad code practice, as well as quite numerous in my projects.

有没有获得正确帧大小的方法或地方?

Is there a way or place to get correct frame sizes?

编辑

我发现使用高度/宽度约束而不是框架宽度高度更可靠.不过,这可能会增加需要大量新 IBOutlets 来链接项目的高度/宽度约束的开销.

I've discovered that using the height/width constraint instead of frame width height is more reliable. This may add the overhead of needing lot of new IBOutlets to link the height/width constraints on items though.

现在我已经创建了一个 UIView 类别,它可以让我直接访问视图的高度/宽度约束,而无需 IBOutlets.对于最少的使用,小循环应该没什么大不了的.显然,没有创建宽度/高度约束的 IB 项目的结果不能保证.对于常数,可能最多返回 0,或者更糟.此外,如果您没有高度/宽度约束并且您的视图是根据前导/尾随约束动态调整大小的,那么这将不起作用.

For now I've created a UIView category that lets me access a View's height/width constraints directly without the IBOutlets. For minimal use the small loop shouldn't be a big deal. Results not guaranteed for IB items without the width/height constraints created yet obviously. Probably returns 0 at best for the constant, or worse. Also, if you don't have a height/width constraint and your view is sized dynamically based on leading/trailing constraints, this won't work.

-viewDidLoad 似乎具有正确的帧大小,但如果您在此处进行修改,通常会导致 UI 的视觉变化.

-viewDidLoad appears to have correct frame size, but will often result in a visual change to the UI if you do modifications here.

UIView+WidthHeightConstraints.h

@interface UIView (WidthHeightConstraints)

-(NSLayoutConstraint*)widthConstraint;
-(NSLayoutConstraint*)heightConstraint;
-(NSLayoutConstraint*)constraintForAttribute:(NSLayoutAttribute)attribute;

@end

UIView+WidthHeightConstraints.m

#import "UIView+WidthHeightConstraints.h"

@implementation UIView (WidthHeightConstraints)

-(NSLayoutConstraint*)widthConstraint{
    return [self constraintForAttribute:NSLayoutAttributeWidth];
}
-(NSLayoutConstraint*)heightConstraint {
    return [self constraintForAttribute:NSLayoutAttributeHeight];
}
-(NSLayoutConstraint*)constraintForAttribute:(NSLayoutAttribute)attribute {
    NSLayoutConstraint *targetConstraint = nil;
    for (NSLayoutConstraint *constraint in self.constraints) {
        if (constraint.firstAttribute == attribute) {
            targetConstraint = constraint;
            break;
        }
    }
    return targetConstraint;
}

@end

编辑 2

上述类别已被证明仅部分有效.主要是因为 ios 似乎自动添加了几个额外的高度/宽度约束副本,它们的类型为 NSContentSizeLayoutConstraint,实际上与正常约束的大小不同.NSContentSizeLayoutConstraint 也是一个私有类,所以我不能用 isKindOfClass 过滤掉它们.我还没有找到另一种有效测试这些的方法.这很烦人.

The category above has proven only partially effective. Mainly because ios appears to auto add a couple extra height/width constraint duplicates, that are of type NSContentSizeLayoutConstraint, which are actually not the same size as the normal constraint. The NSContentSizeLayoutConstraint is also a private class so I can't do isKindOfClass to filter those out. I haven't found another way to effectively test for those yet. This is annoying.

推荐答案

您描述的最常见问题仅出现在 iOS 10 中,可以通过添加此行来解决(如果需要):

The most common issues you describe are appearing in iOS 10 only and can be solved by adding this line (if necessary):

self.view.layoutIfNeeded()

就在代码上方,负责改变约束、layer.cornerRadius 等

just above the code, that is responsible for changing constraint, layer.cornerRadius etc.

将与框架/图层相关的代码放入 viewDidLayoutSubviews() 方法中:

place your code related to frames / layers into viewDidLayoutSubviews() method:

override func viewDidLayoutSubviews() {

    super.viewDidLayoutSubviews()
    view.layer.cornerRadius = self.myView.frame.size.width/2
    view.clipsToBounds = true

    ... etc
}

这篇关于ios10:viewDidLoad 框架宽度/高度未正确初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆