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

遇到的第一个问题是,常见的拐角圆角未能全面解决:

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

在代码中,任何依赖帧大小进行计算的东西都会出现进一步的问题.

cellForRowAtIndexPath 

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

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

有没有一种方法或地方可以获得正确的框架尺寸?

EDIT

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

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

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

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

EDIT 2

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

推荐答案

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

self.view.layoutIfNeeded()

就在代码上方,负责更改约束层.转弯半径等.

OR

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

override func viewDidLayoutSubviews() {

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

    ... etc
}

Objective-c相关问答推荐

UICollectionView:一行或一列

使用 AVAudioplayer 在后台播放音乐

将 NSInteger 变量传递给 NSMutableDictionary 或 NSMutableArray

让 iPhone sleeping

在我的 UIImageView 的子类中没有调用 drawRect

如何在 iPhone 应用程序的 UINavigationBar 中添加图像

在 viewDidAppear 之前无法正确设置框架

如何连续关闭 2 个模态视图控制器?

如何构建一个 Objective-C 静态库?

捕获组在 NSRegularExpression 中不起作用

NSMutableArray 判断对象是否已经存在

Grand Central Dispatch (GCD) 与 performSelector - 需要更好的解释

为什么不鼓励使用伞式框架?

有没有办法更新单个 UITableViewCell 的高度,而无需重新计算每个单元格的高度?

从 NSRange 创建 UITextRange

如何将 NSOperationQueue 与 NSURLSession 一起使用?

Highlighted 和 Selected UIButton 的 State 有什么区别?

在 UITableView 的 iOS 文档目录中列出保存的文件?

从带有参数的方法名称创建 Select 器

如何定义 UIColor 的常量值?