it-swarm.com.ru

Проблема авторазметки на 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 - высота ячейки по умолчанию, но я определил свои пользовательские высоты в делегате табличного представления, так почему у ячейки contentView есть это ограничение? Что может вызвать это?

В iOS6 этого не происходит, и все выглядит отлично как на iOS6, так и на iOS7.

Мой код довольно большой, поэтому я не буду публиковать его здесь, но не стесняйтесь просить Pastebin, если вам это нужно.

Чтобы уточнить, как я это делаю, при инициализации ячейки:

  • Я создаю все свои ярлыки, кнопки и т.д.
  • Я установил для их свойства translatesAutoresizingMaskIntoConstraints значение NO
  • Я добавляю их как подпредставления contentView ячейки
  • Я добавляю ограничения на contentView

Мне также очень интересно понять, почему это происходит только на iOS7.

104
Alexis

У меня была и эта проблема. Похоже, что кадр contentView не обновляется до тех пор, пока не будет вызвано layoutSubviews, однако кадр ячейки обновляется раньше, и для кадра contentView установлено значение {0, 0, 320, 44} во время оценки ограничений.

После более подробного изучения содержимого ViewView выясняется, что 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;
}
132
liamnichols

Очевидно, что-то не так с UITableViewCell и UICollectionViewCell на iOS 7 с использованием iOS 8 SDK.

Вы можете обновить contentView ячейки, когда ячейка используется повторно следующим образом:

Для статического 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

35
KoCMoHaBTa

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

В вашем случае UIImageView имеет интервал 15 сверху, а нижний - 0 снизу. Если вы установите приоритет этих ограничений на 999 (вместо 1000), приложение не будет аварийно завершать работу, потому что ограничения не требуются.

После вызова метода layoutSubviews ячейка будет иметь правильную высоту, и ограничения могут быть удовлетворены в обычном режиме.

13
Steven

Я все еще не нашел хорошего решения для раскадровок ... Некоторая информация также здесь: 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" на height = "9999"
  • щелкните правой кнопкой мыши раскадровку
  • Открыть как -> Интерфейсный Разработчик
  • запустите ваше приложение и проверьте вывод
9
asdfasdfads

Может быть, установить приоритет просмотра более 750 и менее 1000 может решить.

"<NSLayoutConstraint:0xac43620 V:[UIImageView:0xac47f50(62)]>",
3
heramerom

Просто увеличьте высоту ячейки по умолчанию. Похоже, проблема в том, что содержимое ячейки больше, чем заданный по умолчанию (начальный) размер ячейки, что нарушает некоторые ограничения неотрицательности, пока ячейка не будет изменена до ее фактического размера.

3
Vadim Yelagin

У меня такая же проблема. Мое решение основано на других выше:

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        // initialize my stuff
        [self layoutSubviews]; // avoid debugger warnings regarding constraint conflicts
    }
    return self;
}

Бест, Алессандро

1
Cormentis

Я закончил тем, что вообще не использовал UITableViewCell в конструкторе ... Я создаю там пользовательское представление и добавляю его в представление содержимого ячейки программным способом ... С некоторыми категориями справки также нет шаблонного кода ...

0
Renetik

Я также столкнулся с этой проблемой, и ни одно из предложений не помогло. В моем случае у меня была ячейка выбора размера, и она содержала collectionView внутри (каждая ячейка collectionView содержала полноразмерное изображение). Теперь высота ячейки была немного больше (60), чем collectionView (50) и изображения внутри него (50). Из-за этого представление collectionView имеет выравнивание снизу к ограничению superview со значением 10. В этом случае я получил предупреждение, и единственный способ исправить это - сделать высоту ячейки такой же, как и ее collectionView.

0
Centurion

Если он работает нормально в iOS8 и получает предупреждение в iOS7, вы можете выполнить поиск исходного кода раскадровки и найти правильный tableviewCell, а затем добавить атрибут rect после строки tableviewCell. Спасибо кучумовн .

<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" .../>
                                <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
0
NSDeveloper