web-dev-qa-db-ja.com

アプリを起動するたびに「-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]];    

そしてそれは私にこのエラーを与えます:

*キャッチされなかった例外 'NSInternalInconsistencyException'が原因でアプリを終了しています、理由: '-layoutSubviewsの実行後も自動レイアウトが必要です。 UITableViewの-layoutSubviewsの実装では、superを呼び出す必要があります。

一体何が間違っているのですか?行が0の場合、そのコードをtableView:numberOfRowsInSection:で呼び出します。

18
Doug Smith

UIScrollViewをサブクラス化していて、iOS 7で同じエラーメッセージを受け取りました(8ではありません)。

次のような方法でlayoutSubviewsをオーバーライドしていました。

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

スーパーのlayoutSubviewsへの呼び出しをメソッドの最後のものに移動することで、問題を解決しました。

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

[self.view layoutIfNeeded]

お役に立てれば

2
Zay

同じ問題がありました。 self.tableViewにビューを追加し、制約を使用しました。 addSubviewを介してビューをテーブルビューに追加しないでください。ただし、ヘッダー、フッター、またはセルとして追加してください。

2
dergab

また、テーブルビューのマスク変換を無効にする必要があります。

1
Cocoanetics

私にとってはこれでした

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];
}
1
MUH Mobile Inc.

チェックアウト ITableViewCellサブクラスで-layoutSubviewsを実行した後も自動レイアウトが必要です 質問は同じように見えます。

答えの1つ で述べたカテゴリを実装することができました。これで問題は解決しました。ただし、その特定の回答で説明されているように、UITableViewクラスではなく、UITableViewCellクラスにカテゴリを作成する必要がありました。

0
lidsinker

考えられる解決策は、noArticlesViewをテーブルに直接追加することではなく、UITableViewをコンテナUIView内に配置することです(最終的には、コンテナのフレームに合うようにテーブルの制約を設定します) )次に、設定したのと同じ制約を使用して、コード内の同じ場所、つまり-tableView:numberOfRowsInSection:noArticlesViewメソッド内で、UITableViewDataSourceをコンテナーに制約します。簡単な例でテストしたところ、うまくいきました。
コードに適用する必要のある変更は、UITableViewControllerをUIViewControllerに置き換え、コンテナビューを追加することです(このような場合、テーブルをViewControllerのビューに正確に合わせる必要がある場合を除く)このビューはコンテナです)次に、noArticleViewをテーブルではなくコンテナに制約します。私のサンプルコードは、この回答の下部にあります。
問題の理由とこの解決策が機能する理由について可能な限り説明しようとしますが、説明の一部は推測に基づいているため、完全に正確ではないことを考慮してください。
まず、iOSでビュー階層のレンダリングプロセスがどのように機能するかについて簡単に説明します。レイアウトエンジンの最初のステップは、ビュー階層内のすべてのビューとサブビューのサイズと位置を決定することです。通常、これは、ビューとサブビューのサイズと位置を決定するために自動レイアウト制約が評価される反復アプローチで実行され、次に各ビューの-layoutSubviewsメソッドが微調整のために呼び出されます。これは、変更できることを意味します。制約が評価された後のレイアウト。レイアウトエンジンに必要なのは、-layoutSubviewsメソッドが制約を再度変更した場合、反復プロセスを許可するために-[super layoutSubviews]を再度呼び出す必要があることです。これが行われない場合、レイアウトエンジンは例外を発生させます。 UITableViewの場合、tableView:numberOfRowsInSection:メソッドは内部UITableView layoutSubviewsメソッド内のどこかで呼び出され、このメソッドは[superlayoutSubviews]を呼び出さないと思います。したがって、テーブルデータソースメソッドが内部テーブル制約を更新すると、メソッドの最後に例外がトリガーされます。私が提案するソリューションは、テーブルに適用される唯一の制約がコンテナに対する外部制約であるため、レイアウトプロセスの最初の段階で評価されますが、テーブルデータソースメソッドで追加された制約はテーブルに関連しないため、機能しますテーブルの外部のビュー(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;
}
0
viggio24

「記事なしビュー」をテーブルのカスタムヘッダーとして追加して、正しく配置されていることを確認できます。

0
ilya n.