18

由于我添加了以下代码,每次我的应用程序打开UITableViewController它都会崩溃:

 self.noArticlesView = [[UIView alloc] init];
 self.noArticlesView.translatesAutoresizingMaskIntoConstraints = NO;
 self.noArticlesView.backgroundColor = [UIColor colorWithRed:0.961 green:0.961 blue:0.961 alpha:1];

 [self.view addSubview:self.noArticlesView];

 [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.noArticlesView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]];
 [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.noArticlesView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]];
 [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.noArticlesView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0]];
 [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.noArticlesView attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:0.0]];    

它给了我这个错误:

*由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“执行 -layoutSubviews 后仍需要自动布局。UITableView 的 -layoutSubviews 实现需要调用 super.'

我到底做错了什么?tableView:numberOfRowsInSection:当有 0 行时,我调用该代码。

4

9 回答 9

14

我正在继承 UIScrollView 并在 iOS 7(但不是 8)上收到相同的错误消息。

我以类似于以下方式覆盖 layoutSubviews:

- (void)layoutSubviews {
    [super layoutSubviews];
    // code to scroll the view
}

我通过将调用超级的 layoutSubviews 移动到方法中的最后一件事来解决了这个问题:

- (void)layoutSubviews {
    // code to scroll the view
    [super layoutSubviews];
}
于 2015-02-14T02:00:23.930 回答
2

有同样的问题。向 self.tableView 添加了视图并使用了约束。不要通过 addSubview 将视图添加到表格视图中:而是将它们添加为页眉、页脚或单元格。

于 2014-09-29T09:41:03.467 回答
2

[self.view layoutIfNeeded]

希望这可以帮助

于 2014-11-25T13:14:22.613 回答
1

您还需要禁用表视图的掩码转换。

于 2013-11-11T06:41:55.940 回答
1

对我来说是这样

self.tableView.backgroundView = self.emptyView;

我改成了这个

    NSComparisonResult order = [[UIDevice currentDevice].systemVersion compare: @"8.0" options: NSNumericSearch];
if (order == NSOrderedSame || order == NSOrderedDescending) {
    // OS version >= 8.0
    self.tableView.backgroundView = self.emptyView;
}else{
    [self.tableView.backgroundView addSubview:self.emptyView];
}
于 2015-05-07T19:05:07.663 回答
0

一种可能的解决方案不是noArticlesView直接在表中添加,而是将其UITableView放入容器内部UIView(最终设置表约束以适应容器框架),然后noArticlesView使用您设置的相同约束和在代码中的相同位置,即-tableView:numberOfRowsInSection: UITableViewDataSource方法内部。我用一个简单的例子对其进行了测试,它奏效了。
您需要对代码应用的更改是UITableViewController用 UIViewController 替换,添加容器视图(除非您希望表与视图控制器的视图完全匹配,在这种情况下,此视图是容器),然后约束您的 noArticleView到容器而不是桌子。我的示例代码在这个答案的底部。
我将尝试对问题的原因以及该解决方案为何有效的原因做出可能的解释,但考虑到我的部分解释是基于猜测,因此不能完全准确。
首先简要解释一下视图层次渲染过程在 iOS 中是如何工作的。布局引擎的第一步是确定视图层次结构中所有视图和子视图的大小和位置。通常这是通过迭代方法完成的,其中评估自动布局约束,以确定视图和子视图的大小和位置,然后 -layoutSubviews调用每个视图的方法进行微调:这意味着您可以在约束后更改布局评估。布局引擎需要的是,如果-layoutSubviews方法再次改变约束,那么-[super layoutSubviews]必须再次调用以允许迭代过程:如果这没有发生,布局引擎会引发异常。在 UITableView 的情况下,我的猜测是 tableView:numberOfRowsInSection: 方法在内部 UITableView layoutSubviews 方法中的某处被调用,并且此方法不调用 [super layoutSubviews]。因此,如果您的表数据源方法更新了内部表约束,则在方法结束时会触发异常。我提出的解决方案有效,因为应用于表的唯一约束是对容器的外部约束,因此在布局过程的第一阶段进行了评估,而在表数据源方法中添加的约束与表无关,因为它们应用于表外部的视图(容器和 noArticlesView),因此它们不会



//
//  RootController.h

#import 

@interface RootController : UIViewController

@property (nonatomic,strong) IBOutlet UITableView *table;
@property (nonatomic,strong) IBOutlet UIView *container;

@end

//
//  RootController.m


#import "RootController.h"

@implementation RootController

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.

    UIView *_v = [[UIView alloc] init];
    _v.backgroundColor=[UIColor redColor];
    _v.translatesAutoresizingMaskIntoConstraints=NO;

    [self.container addSubview:_v];
    NSLayoutConstraint *_c1 = [NSLayoutConstraint constraintWithItem:_v
                                                            attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.container attribute:NSLayoutAttributeTop multiplier:1.0 constant:20.0];
    NSLayoutConstraint *_c2 = [NSLayoutConstraint constraintWithItem:_v
                                                           attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.container attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-20.0];
    NSLayoutConstraint *_c3 = [NSLayoutConstraint constraintWithItem:_v
                                                           attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self.container attribute:NSLayoutAttributeLeft multiplier:1.0 constant:20.0];
    NSLayoutConstraint *_c4 = [NSLayoutConstraint constraintWithItem:_v
                                                           attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self.container attribute:NSLayoutAttributeRight multiplier:1.0 constant:-20.0];
    [self.container addConstraints:@[_c1,_c2,_c3,_c4]];

    return 0;
}
于 2013-11-26T22:24:36.917 回答
0

您可以将“无文章视图”添加为表格中的自定义标题,以确保其位置正确。

于 2013-11-26T20:56:48.420 回答
0

使用 UITableViewCell 子类签出“执行 -layoutSubviews 后仍需要自动布局”,因为问题似乎相同。

我能够实现为我解决问题的答案之一中提到的类别。但是,我必须在类上创建类别,UITableView而不是UITableViewCell在该特定答案中讨论的类。

于 2013-11-26T16:48:20.217 回答
-8

我取消选中视图控制器上的自动布局,现在没有发生崩溃

于 2014-09-04T12:27:14.393 回答