执行 -layoutSubviews 后仍需要自动布局,使用UITableViewCell子类。

115
我正在使用XCode 4.5和iOS 6开发一个带有自定义单元格的简单表视图的应用程序。在iOS 5及以下版本中已经完成了一百次以上,但由于新的自动布局系统,在这里遇到了很多麻烦。
我在IB中设置了表视图和原型单元格,添加了子视图并将它们连接为IBOutlets,然后设置代理和数据源。然而,现在每当从cellForRowAtIndexPath获取第一个单元格时,我会收到以下错误:
Assertion failure in -[ShopCell layoutSublayersOfLayer:], /SourceCache/UIKit_Sim/UIKit-2372/UIView.m:5776
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. ShopCell's implementation of -layoutSubviews needs to call super.'
我没有在我的子类化单元格(ShopCell)中实现-layoutSubviews方法,即使我尝试这样做并添加super调用,仍然会收到相同的错误。如果我在IB中删除单元格中的子视图,并将其更改为标准UITableViewCell,则一切正常,尽管当然我留下了没有数据的单元格。
我几乎可以确定有些简单的东西我错过了,但找不到任何文档或指南来提示我做错了什么。感谢任何帮助。

如果使用自动布局,请在调试器区域尝试lldb [[UIWindow keyWindow] _autoLayoutTrace]。 - A-Live
3
你是不是在使用UIView代替UITableViewCell作为自定义单元格?我之前也遇到了同样的问题。我一开始使用UIView作为自定义单元格,并向其中添加子视图。后来改用UITableViewCell就解决了问题。 - user1705389
取消检查检视器中的autoLayout框,然后清理并运行。它一定会起作用。 - Nico
我曾经遇到过同样的问题,为此苦苦挣扎了一段时间。user1705389的解决方案帮助了我。对我来说,这个问题出现在一个原本是单元格的表视图页脚上,我忘记将单元格的超类从UITableViewCell更改为简单的UIView。 - ShayDavidson
我在iOS 7.1中遇到了这个错误,但在iOS 8中没有。 - onmyway133
显示剩余2条评论
31个回答

2
将子视图添加到单元格的contentView而不是单元格本身。 所以,不要这样做:

[self addSubview:someView];

而是必须使用

[self.contentView addSubview:someView];


2

我遇到了这个问题,似乎与UITableViewCell子类有关,因为原型单元格特别是将其他自定义UIView子类添加到它们中。我在这里强调“自定义”,因为对于只有UIKit子视图的单元格,我已经成功了,但是在尝试构建我创建的视图的约束时失败了,抛出了作者所述的错误。

我不得不将我的单元格分成独立的nib文件,而不使用AutoLayout。

让我们希望苹果能够清理这个混乱。


1
我没有得到任何关于这个问题的适当解决方案,但你可以通过使用框架并不设置 translatesAutoresizingMaskIntoConstraints 属性为 No(默认为 yes,所以不要设置它)来解决它。
CGRect headerViewFrame = CGRectMake(0,0,320,60); //Frame for your header/footer view
UIView *tableHeaderView = [[UIView alloc] initWithFrame:headerViewFrame];
tableHeaderView.translatesAutoresizingMaskIntoConstraints = Yes; //Or don't set it at all
[self.tableView setTableHeaderView:tableHeaderView];

1

我遇到这个问题是因为最初在一个xib文件中添加的是UIView而不是UITableViewCell。


1
我通过将背景UIImageView的backgroundView连接器与我的UIButton自定义的accessoryView连接器解耦来消除了这个错误。我怀疑它们并不是用于我使用的方式。

1
我今天第一次遇到了这个问题。在此之前,我有使用原型UITableViewCell子类的各种经验,但从未遇到过这个问题。我正在处理的单元格与众不同的是,我有一个IBOutlet指向-backgroundView,我正在使用它来着色单元格。我发现,如果我创建一个新属性,并仍然添加一个新的UIView,该UIView可以延伸整个单元格的跨度,那么这个断言就会消失。为了验证这是否是原因,我回到将此视图附加到backgroundView输出口的方式,断言重新出现了。自从做出这个改变以来,在子类化的原型UITableViewCell中使用AutoLayout没有出现其他问题。

0
解决方案:在调用 super layoutSubviews 之前更改约束。
- (void)layoutSubviews
{

    [self _updateConstraints];

    [super layoutSubviews];
}

0

我修改了Carl Lindberg的答案,改为覆盖UITableView,这样它就对我起作用了:

UITableView+AutoLayoutFix.h

@interface UITableView (AutoLayoutFix)
@end

UITableView+AutoLayoutFix.m

#import <objc/runtime.h>

@implementation UITableView (AutoLayoutFix)

+ (void)load
{
    Method existingMethod = class_getInstanceMethod(self, @selector(layoutSubviews));
    Method newMethod = class_getInstanceMethod(self, @selector(_autolayout_replacementLayoutSubviews));

    method_exchangeImplementations(existingMethod, newMethod);
}

- (void)_autolayout_replacementLayoutSubviews
{
    [super layoutSubviews];
    [self _autolayout_replacementLayoutSubviews]; // not recursive due to method swizzling
    [super layoutSubviews];
}

@end

然后在MyViewController.m中,我只是导入了这个类别:

#import "UITableView+AutoLayoutFix.h"

0
在某些情况下,这可以轻松解决布局问题(取决于您的布局)。在您的UITableView子类中,在awakeFromNib或init中设置自动调整掩码:
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

默认情况下,它设置为UIViewAutoresizingNone


这解决了我遇到的问题。我在表格单元格中使用自动布局,结合 [tableViewCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height 来获取高度,然后在 heightForRowAtIndexPath 中使用。 - NathanAldenSr

0
在我的情况下,用于UITableView自动布局的引用UIImageView被分配给UITableView的backgroundView。
self.tableView.backgroundView = self.tableBackgroundImageView;

所以,我从UIView(根视图)中删除了UIImageView作为backgroundView,并重置(删除)了所有对该UIImageView的自动布局引用。我将该UIImageView放在UIView(根视图)外部作为背景。然后在代码中将其分配给UITableView的backgroundView。

然后修复了问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接