【问题标题】:Why am I getting a "Auto Layout still required after executing -layoutSubviews" error every time my app launches now?为什么我现在每次启动应用程序时都会收到“执行 -layoutSubviews 后仍需要自动布局”错误?
【发布时间】:2013-11-19 04:00:03
【问题描述】:

由于我添加了以下代码,每次我的应用打开此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。'

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

【问题讨论】:

  • 不是专家,但我也遇到了这个问题,我认为这是因为 UITableView 实现了它自己的 layoutSubviews 版本(或自动布局所需的其他类似方法)。我提出你的问题,因为我也想得到答案:)
  • 是的,我可能只需要重新使用框架(我之前所做的),但自动布局会很好用。 ://
  • 我为此回到了框架,但是一旦一切都带有自动布局,这真的很不方便......
  • self.view 是一个表格视图,而 self.noArticlesView 是一个应该覆盖显示没有表格单元格的视图?
  • 嗯,这一切都在UITableViewController 子类中运行,所以我想self.view 是一个tableview。您对self.noArticlesView 的看法是正确的。

标签: ios objective-c uitableview autolayout nslayoutconstraint


【解决方案1】:

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

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

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

我解决了这个问题,把对 super 的 layoutSubviews 的调用移到方法中的最后一件事:

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

【讨论】:

  • 我遇到了同样的问题。我的子类-(void)layoutSubViews 会修改一些约束常量。在修改约束之前调用[super layoutSubviews]会在iOS7(但不是8)中崩溃。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    [self.view layoutIfNeeded]

    希望对你有帮助

    【讨论】:

    • 请为您的方法添加更多详细信息,而不仅仅是“单行”但是,谢谢您的回答。
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      对我来说是这样的

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

      【讨论】:

        【解决方案6】:

        结帐"Auto Layout still required after executing -layoutSubviews" with UITableViewCell subclass,因为问题似乎是相同的。

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

        【讨论】:

          【解决方案7】:

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

          【讨论】:

            【解决方案8】:

            一种可能的解决方案是不要将noArticlesView 直接添加到表中,而是将UITableView 放在容器UIView 中(最终设置表约束以适应容器框架),然后约束你的@ 987654324@ 到容器,使用您设置的相同约束并在代码中的相同位置,即在 -tableView:numberOfRowsInSection: UITableViewDataSource 方法内。 我用一个简单的例子对其进行了测试,它确实有效。
            您需要对代码应用的更改是用 UIViewController 替换 UITableViewController,添加一个容器视图(除非您希望您的表完全适合视图控制器的视图,在这种情况下,这个视图就是容器)然后将您的 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;
            }
            

            【讨论】:

              【解决方案9】:

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

              【讨论】:

                猜你喜欢
                • 2014-10-23
                • 2015-11-10
                • 2015-07-09
                • 2012-09-18
                • 2013-07-28
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多