2013-11-07 3 views
18

Поскольку я добавил следующий код, каждый раз, когда мое приложение открывает этот UITableViewController он выходит из строя:Почему я получаю «Автоматический макет, который все еще требуется после выполнения -layoutSubviews» при каждом запуске приложения?

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

И это дает мне эту ошибку:

* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Auto Layout still required after executing -layoutSubviews. UITableView's implementation of -layoutSubviews needs to call super.'

Что же я делаю не так? Я вызываю этот код в tableView:numberOfRowsInSection:, когда есть 0 строк.

+1

Не эксперт, но у меня тоже была эта проблема, и я думаю, что это потому, что UITableView реализует собственную версию layoutSubviews (или других методов, которые необходимы для автоматического макета). Я поднимаю ваш вопрос, потому что я тоже хотел бы получить ответ :) – AncAinu

+0

Да, мне просто нужно вернуться к использованию фреймов для этого (что я сделал ранее), но Auto Layout было бы неплохо использовать. :/ –

+1

Я вернулся к кадру для этого, но это действительно не удобно, когда все с автозапуском ... – AncAinu

ответ

1

Вам также необходимо отключить трансляцию маски для представления таблицы.

0

Оформить заказ "Auto Layout still required after executing -layoutSubviews" with UITableViewCell subclass, так как вопрос будет таким же.

Я смог реализовать категорию, указанную в one of the answers, которая решила проблему для меня. Однако мне пришлось создать категорию в классе UITableView вместо класса UITableViewCell, как это обсуждается в этом конкретном ответе.

0

Вы можете добавить свой «нет статей» в качестве пользовательского заголовка в таблице, чтобы убедиться, что он правильно расположен.

0

Возможное решение не добавлять noArticlesView непосредственно в таблице, но это поместить UITableView внутри контейнера UIView (в конце концов, устанавливая таблицы ограничений, в соответствии с рамой контейнера), а затем тяготы вашего noArticlesView в контейнер, используя те же ограничения, которые вы задали, и в том же месте в вашем коде, который находится внутри метода -tableView:numberOfRowsInSection:UITableViewDataSource. Я протестировал его на простом примере, и он сработал.
Изменения, которые необходимо применить к вашему коду, - это заменить UITableViewController на UIViewController, добавить представление контейнера (если вы не хотите, чтобы ваша таблица точно соответствовала представлению контроллера вида, в этом случае это представление является контейнером), а затем ограничьте свой noArticleView контейнером вместо таблицы. Мой примерный код находится в нижней части этого ответа.
Я попытаюсь сделать возможное объяснение причины проблемы и почему это решение работает, но подумайте, что часть моего объяснения основана на догадках, поэтому она не может быть полностью точной.
Прежде всего краткое описание того, как процесс рендеринга иерархии представлений работает в iOS. Первым шагом для механизма компоновки является определение размера и положения всех представлений и подпунктов в иерархии представлений. Обычно это выполняется с помощью итеративного подхода, в котором оцениваются ограничения автоматического макета, чтобы определить размер и положение просмотров и подсмотров, а затем метод -layoutSubviews каждого вида предназначен для точной настройки: это означает, что вы можете изменить макет после ограничений оцениваются. То, что требует механизм компоновки, состоит в том, что если метод -layoutSubviews снова изменяет ограничения, то необходимо снова вызвать -[super layoutSubviews], чтобы разрешить итеративный процесс: если этого не происходит, механизм компоновки вызывает исключение. В случае UITableView моя догадка заключается в том, что метод tableView: numberOfRowsInSection: вызывается где-то внутри внутреннего метода UITableView layoutSubviews, и этот метод не вызывает [super layoutSubviews]. Поэтому, если ваш метод источника данных таблицы обновляет внутренние ограничения таблицы, в конце метода инициируется исключение. Решение, которое я предлагаю, работает, потому что единственным ограничением, применяемым к таблице, является внешнее ограничение для контейнера, поэтому оно оценивается на первом этапе процесса компоновки, тогда как ограничения, добавленные в методе источника данных таблицы, не имеют отношения к таблице, поскольку они применяются к представлениям, внешним по отношению к таблице (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; 
} 
-8

я непроверенный Автокомпоновка на контроллере представления аварии не происходит сейчас

2

была такая же проблема. Добавлено представление (ы) для self.tableView и используемых ограничений. Не добавляйте представления в представление таблицы через addSubview: но добавляйте их в виде заголовков, нижних колонтитулов или ячеек.

2

[self.view layoutIfNeeded]

Надеется, что это помогает

+3

Пожалуйста, добавьте больше деталей для вашего подхода, и не только «однострочный» Однако, спасибо за ответ. –

14

Я подклассы UIScrollView и получил то же самое сообщение об ошибке на IOS 7 (но не 8).

я переопределение layoutSubviews аналогично следующему:

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

Я решил проблему, переместив вызов layoutSubviews супер, чтобы быть последним, что в методе:

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

У меня такая же проблема. My '- (void) layoutSubViews' подкласса изменяет некоторую константу константы. Вызов '[super layoutSubviews]' перед изменением ограничения приведет к сбою в iOS7 (но не 8). – AechoLiu

1

для меня это было

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]; 
} 
Смежные вопросы