Ios 为什么我会得到一个“a”;执行-layoutSubviews“后仍需要自动布局”;现在每次启动我的应用时都会出错?

Ios 为什么我会得到一个“a”;执行-layoutSubviews“后仍需要自动布局”;现在每次启动我的应用时都会出错?,ios,objective-c,uitableview,autolayout,nslayoutconstraint,Ios,Objective C,Uitableview,Autolayout,Nslayoutconstraint,由于我添加了以下代码,每次我的应用程序打开此UITableViewController时,它都会崩溃: self.noArticlesView = [[UIView alloc] init]; self.noArticlesView.translatesAutoresizingMaskIntoConstraints = NO; self.noArticlesView.backgroundColor = [UIColor colorWithRed:0.961 green:0.961 blue

由于我添加了以下代码,每次我的应用程序打开此
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的-LayoutSubView实现需要调用super


我到底做错了什么?当有0行时,我在
表格视图:numberOfRowsInSection:
中调用该代码。

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

签出,因为问题似乎是相同的


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

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

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

我在视图控制器上取消选中了“自动布局”。现在没有发生崩溃。将视图添加到self.tableView并使用了约束。不要通过addSubview将视图添加到表视图:而是将它们添加为页眉、页脚或单元格。

[self.view layoutifneed]


希望这能有所帮助

我在对UIScrollView进行子类化时,在iOS 7(但不是8)上收到了相同的错误消息

我以类似于以下的方式覆盖布局子视图:

- (void)layoutSubviews {
    [super layoutSubviews];
    // code to scroll the view
}
我通过将对super的LayoutSubView的调用移到方法中的最后一项来解决此问题:

- (void)layoutSubviews {
    // code to scroll the view
    [super layoutSubviews];
}
对我来说是这样的

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

我不是专家,但我也有这个问题,我认为这是因为UITableView实现了自己版本的LayoutSubView(或自动布局所需的其他类似方法)。我提出了你的问题,因为我也想得到答案:)是的,我可能不得不重新使用框架(我以前做过的)但是使用自动布局会很好/我回到了这个框架,但一旦一切都使用autolayout,它就真的不方便了…是self.view是一个表视图,self.noArticlesView是一个应该覆盖的视图,显示没有表单元格?嗯,这都是在
UITableViewController
子类中操作的,所以我想,
self.view
是一个tableview。你对自我的看法是正确的。请为你的方法添加更多细节,而不仅仅是“一行”,谢谢你的回答。我遇到了同样的问题。子类的My
-(void)LayoutSubView
将修改一些约束常量。在修改约束之前调用
[super layoutSubviews]
将在iOS7中崩溃(但不是在8中)。