每当我的应用程序启动时,为什么我会在执行“-layoutSubviews”后仍然需要“自动布局”?

由于我添加了下面的代码,每当我的应用程序打开这个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]]; 

它给了我这个错误:

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

我究竟做错了什么? 我在tableView:numberOfRowsInSection:调用该代码tableView:numberOfRowsInSection:当有0行时。

我是inheritanceUIScrollView并收到iOS 7(但不是8)相同的错误消息。

我以类似于以下的方式重写layoutSubviews:

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

我通过将调用移动到super的layoutSubviews解决了这个问题,是方法中的最后一件事情:

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

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

[self.view layoutIfNeeded]

希望这可以帮助

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

对我来说是这样的

 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]; } 

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

我能够执行其中一个解决问题的答案中提到的类别。 不过,我不得不在UITableView类而不是UITableView类中创build类别,正如在特定答案中所讨论的那样。

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

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

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