Проблема с ограничениями автоматической компоновки на iOS7 в UITableViewCell
Я использую автоматические ограничения компоновки программно для компоновки своих пользовательских ячеек UITableView, и я правильно определяю размеры ячеек в tableView:heightForRowAtIndexPath:
Он отлично работает на iOS6, и он отлично выглядит в iOS7, а также
НО, когда я запускаю приложение на iOS7, вот вид сообщения, который я вижу на консоли:
Break on objc_exception_throw to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2013-10-02 09:56:44.847 Vente-Exclusive[76306:a0b] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0xac4c5f0 V:|-(15)-[UIImageView:0xac47f50] (Names: '|':UITableViewCellContentView:0xd93e850 )>",
"<NSLayoutConstraint:0xac43620 V:[UIImageView:0xac47f50(62)]>",
"<NSLayoutConstraint:0xac43650 V:[UIImageView:0xac47f50]-(>=0)-[UIView:0xac4d0f0]>",
"<NSLayoutConstraint:0xac43680 V:[UIView:0xac4d0f0(1)]>",
"<NSLayoutConstraint:0xac436b0 V:[UIView:0xac4d0f0]-(0)-| (Names: '|':UITableViewCellContentView:0xd93e850 )>",
"<NSAutoresizingMaskLayoutConstraint:0xac6b120 h=--& v=--& V:[UITableViewCellContentView:0xd93e850(44)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0xac43650 V:[UIImageView:0xac47f50]-(>=0)-[UIView:0xac4d0f0]>
И действительно, мне не нужно одно из ограничений в этом списке:
"<NSAutoresizingMaskLayoutConstraint:0xac6b120 h=--& v=--& V:[UITableViewCellContentView:0xd93e850(44)]>"
и я не могу установить для свойства translatesAutoresizingMaskIntoConstraints
contentView
значение NO = > , это испортит всю ячейку.
44 - это высота ячеек по умолчанию, но я определил свои пользовательские высоты в делегате представления таблиц, так почему же содержимое cellView имеет это ограничение? Что может быть причиной этого?
В iOS6 это не происходит, и все отлично выглядит как на iOS6, так и на iOS7.
Мой код довольно большой, поэтому я не буду публиковать его здесь, но не стесняйтесь спрашивать пастебин, если он вам нужен.
Чтобы указать, как я это делаю, при инициализации ячейки:
- Я создаю все свои ярлыки, кнопки и т.д.
- Я установил для своего свойства
translatesAutoresizingMaskIntoConstraints
значение NO
- Я добавляю их как подпункты
contentView
ячейки
- Я добавляю ограничения на
contentView
Мне также очень интересно понять, почему это происходит только на iOS7.
Ответы
Ответ 1
У меня также возникла эта проблема.. Похоже, что кадр contentView не обновляется до тех пор, пока не будет вызван layoutSubviews
, однако кадр ячейки обновляется ранее, оставив кадр contentView в {0, 0, 320, 44}
в то время, когда ограничения оцениваются.
После более подробного просмотра contentView, похоже, что autoresizingMasks больше не устанавливаются.
Настройка маски autoresizingMask до того, как вы ограничите свои представления, может решить эту проблему:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier];
if (self)
{
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
[self loadViews];
[self constrainViews];
}
return self;
}
Ответ 2
По-видимому, что-то не так с UITableViewCell и UICollectionViewCell на iOS 7 с помощью IOS 8 SDK.
Вы можете обновить содержимое CellView при повторном использовании ячейки следующим образом:
Для статического UITableViewController:
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
{
cell.contentView.frame = cell.bounds;
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
}
//your code goes here
return cell;
}
#endif
#endif
Поскольку контроллеры Static Table View являются хрупкими и их можно легко сломать, если вы реализуете некоторые методы источника данных или deletegate - есть проверки, которые гарантируют, что этот код будет только скомпилирован и запущен на iOS 7
Он похож на стандартный динамический UITableViewController:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = @"CellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1)
{
cell.contentView.frame = cell.bounds;
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
}
//your code goes here
return cell;
}
Для этого случая нам не нужна дополнительная проверка компиляции, так как требуется выполнить этот метод.
Идея одинаков для обоих случаев, и для UICollectionViewCell, как это прокомментировано в этом потоке: Ошибка авторезистентности UICollectionViewCell contentView в кадре прототипа Storyboard (Xcode 6, iOS 8 SDK) при запуске только на iOS 7
Ответ 3
Поскольку ячейки повторно используются, и высота может меняться в зависимости от содержимого, я думаю, что в целом было бы лучше установить приоритет расстояний меньше, чем требуется.
В вашем случае UIImageView имеет расстояние от 15 до верхней части, а снизу - расстояние от 0 до нижней. Если вы установите приоритет этих ограничений на 999 (вместо 1000), приложение не будет разбиваться, потому что ограничения не требуются.
Как только метод layoutSubviews вызывается, ячейка будет иметь правильную высоту, и ограничения могут быть выполнены нормально.
Ответ 4
Я до сих пор не нашел хорошего решения для раскадровки...
Некоторая информация также здесь:
https://github.com/Alex311/TableCellWithAutoLayout/commit/bde387b27e33605eeac3465475d2f2ff9775f163#commitcomment-4633188
От чего они советуют:
self.contentView.bounds = CGRectMake(0, 0, 99999, 99999);
Я вызвал свое решение:
- щелкните правой кнопкой мыши раскадровку
- Открыть как → Исходный код
- найдите строку "44" там
- он будет похож на
.
<tableView hidden="YES" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="none" allowsSelection="NO" rowHeight="44" ...
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="ChatMessageCell" id="bCG-aU-ivE" customClass="ChatMessageCell">
<rect key="frame" x="0.0" y="22" width="320" height="44"/>
.
- заменить rowHeight = "44" с rowHeight = "9999" и height = "44" с высотой = "9999"
- щелкните правой кнопкой мыши раскадровку
- Открыть As → Interface Builder
- запустите приложение и проверьте вывод
Ответ 5
Просто увеличьте высоту ячейки по умолчанию. Похоже, проблема в том, что содержимое ячейки больше, чем размер ячейки по умолчанию (начальный), нарушая некоторые ограничения без отрицательности, пока ячейка не будет изменена до фактического размера.
Ответ 6
Возможно, установите приоритет вида, превышающий 750, и может решить менее 1000.
"<NSLayoutConstraint:0xac43620 V:[UIImageView:0xac47f50(62)]>",
Ответ 7
У меня была та же проблема. Мое решение, основанное на других выше:
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
// initialize my stuff
[self layoutSubviews]; // avoid debugger warnings regarding constraint conflicts
}
return self;
}
Бест,
Alessandro
Ответ 8
Я тоже столкнулся с этой проблемой, и ни одно из предложений не помогло. В моем случае у меня была ячейка выбора размера, и она содержала collectionView внутри (каждая ячейка collectionView содержала полноразмерное изображение). Теперь размер ячейки был немного больше (60), чем коллекцияView (50) и изображения внутри него (50). Из-за того, что представление collectionView имеет выравнивание нижнего уровня для ограничения супервизора со значением 10. Это случайное предупреждение, и единственный способ исправить это должен был сделать высоту ячейки такой же, как и в его коллекции.
Ответ 9
Я закончил тем, что не использовал UITableViewCell в дизайнере вообще... Я создаю там настраиваемое представление и программно создаю его для представления содержимого ячейки... С некоторыми категориями помощи также нет кодового шаблона...
Ответ 10
Если он отлично работает в iOS8 и получает предупреждение в iOS7, вы можете искать исходный код раскадровки и находить правильный tableviewCell, а затем добавить атрибут rect после строки tableviewCell. Благодаря kuchumovn.
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" .../>
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>