簡體   English   中英

為什么每次我的應用程序啟動時都會出現“執行-layoutSubviews后仍然需要自動布局”錯誤?

[英]Why am I getting a “Auto Layout still required after executing -layoutSubviews” error every time my app launches now?

由於我添加了以下代碼,每次我的應用程序打開此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:調用該代碼tableView:numberOfRowsInSection:當有0行時。

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

有同樣的問題。 添加了對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類代替UITableViewCell類為在特定的答案進行了討論。

您可以在表格中添加“無文章視圖”作為自定義標題,以確保其正確定位。

一個可能的解決方案是不在表中直接添加noArticlesView ,而是將UITableView放在容器UIView (最終設置表約束以適應容器框架)然后將noArticlesView約束到容器,使用相同的約束你設置並在代碼中的相同位置,即-tableView:numberOfRowsInSection: UITableViewDataSource方法。 我用一個簡單的例子測試了它,它起作用了。
您需要應用於代碼的更改是將UITableViewController替換為UIViewController,添加容器視圖(除非您希望表與視圖控制器的視圖完全匹配,在這種情況下此視圖是容器)然后約束您的noArticleView到容器而不是表。 我的示例代碼位於此答案的底部。
我將盡力解釋問題的原因以及為什么這個解決方案有效,但考慮到我的解釋部分是基於猜測所以它不可能完全准確。
首先簡要說明視圖層次結構渲染過程在iOS中的工作原理。 布局引擎的第一步是確定視圖層次結構中所有視圖和子視圖的大小和位置。 通常這是通過迭代方法完成的,其中評估自動布局約束,以確定視圖和子視圖的大小和位置,然后調用每個視圖的-layoutSubviews方法進行微調:這意味着您可以在以后更改布局評估約束。 布局引擎需要的是,如果-layoutSubviews方法再次更改約束,則必須再次調用-[super layoutSubviews]以允許迭代過程:如果不發生這種情況,則布局引擎會引發異常。 在UITableView的情況下,我的猜測是在內部UITableView layoutSubviews方法中的某處調用tableView:numberOfRowsInSection:方法,並且此方法不調用[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;
}

我在視圖控制器上取消選中自動布局,現在沒有發生崩潰

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM