UICollectionViewFlowLayout оценкамItemSize не работает должным образом с iOS12, хотя он отлично работает с iOS 11. *

Для ячеек динамической высоты UICollectionView мы используем,

if let layout = self.collectionViewLayout as? UICollectionViewFlowLayout {
    layout.estimatedItemSize = UICollectionViewFlowLayoutAutomaticSize
}

с надлежащим ограничением высоты и ширины, он отлично работает с версиями iOS 11. *, но он ломается и не делает ячейки динамическими для iOS 12.0

Ответ 1

В моем случае я решил это, явно добавив следующие ограничения в cellView.

class Cell: UICollectionViewCell {
    // ...

    override func awakeFromNib() {
        super.awakeFromNib()

        // Addresses a separate issue and prevent auto layout warnings due to the temporary width constraint in the xib.
        contentView.translatesAutoresizingMaskIntoConstraints = false

        // Code below is needed to make the self-sizing cell work when building for iOS 12 from Xcode 10.0:
        let leftConstraint = contentView.leftAnchor.constraint(equalTo: leftAnchor)
        let rightConstraint = contentView.rightAnchor.constraint(equalTo: rightAnchor)
        let topConstraint = contentView.topAnchor.constraint(equalTo: topAnchor)
        let bottomConstraint = contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
        NSLayoutConstraint.activate([leftConstraint, rightConstraint, topConstraint, bottomConstraint])
    }
}

Эти ограничения уже установлены внутри xib ячейки, но почему-то их недостаточно для iOS 12.

Другие темы, которые предлагали вызвать collectionView.collectionViewLayout.invalidateLayout() в разных местах, не помогли в моей ситуации.

Пример кода здесь: https://github.com/larrylegend/CollectionViewAutoSizingTest

Это применимо к обходному пути для кода из учебника по https://medium.com/@wasinwiwongsak/uicollectionview-with-autosizing-cell-using-autolayout-in-ios-9-10-84ab5cdf35a2:

Ответ 2

Основываясь на ответе ale84 и из-за того, что мне было необходимо, чтобы исправление iOS 12 в нескольких местах я создал расширение UICollectionViewCell, которое я назвал UICollectionViewCell + iOS12:

extension UICollectionViewCell {
    /// This is a workaround method for self sizing collection view cells which stopped working for iOS 12
    func setupSelfSizingForiOS12(contentView: UIView) {
        contentView.translatesAutoresizingMaskIntoConstraints = false
        let leftConstraint = contentView.leftAnchor.constraint(equalTo: leftAnchor)
        let rightConstraint = contentView.rightAnchor.constraint(equalTo: rightAnchor)
        let topConstraint = contentView.topAnchor.constraint(equalTo: topAnchor)
        let bottomConstraint = contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
        NSLayoutConstraint.activate([leftConstraint, rightConstraint, topConstraint, bottomConstraint])
    }
}

А затем в ваших ячейках просмотра коллекции мы делаем что-то вроде этого (если ваша ячейка создана в IB):

override func awakeFromNib() {
    super.awakeFromNib()
    if #available(iOS 12, *) { setupSelfSizingForiOS12(contentView: contentView) }
}

Ответ 3

Вариант версии C версии выше:

-(void)awakeFromNib{
    [super awakeFromNib];

    if (@available(iOS 12.0, *)) {
        // Addresses a separate issue and prevent auto layout warnings due to the temporary width constraint in the xib.
        self.contentView.translatesAutoresizingMaskIntoConstraints = NO;

        // Code below is needed to make the self-sizing cell work when building for iOS 12 from Xcode 10.0:

        NSLayoutConstraint *leftConstraint = [self.contentView.leftAnchor constraintEqualToAnchor:self.leftAnchor constant:0];
        NSLayoutConstraint *rightConstraint = [self.contentView.rightAnchor constraintEqualToAnchor:self.rightAnchor constant:0];
        NSLayoutConstraint *topConstraint = [self.contentView.topAnchor constraintEqualToAnchor:self.topAnchor constant:0];
        NSLayoutConstraint *bottomConstraint = [self.contentView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:0];

        [NSLayoutConstraint activateConstraints:@[leftConstraint, rightConstraint, topConstraint, bottomConstraint]];
    }

}

Для любителей Objective-C, таких как я;) приветствия !!!

Ответ 4

у меня та же проблема. используя UILabels для определения размера коллекции. если я запускаю collectionView.collectionViewLayout.invalidateLayout() прежде чем перезагружать данные, он выполняет обычное задание по размеру меток.

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

Ответ 5

Мне удалось решить эту проблему, поставив такой код в мой подкласс UICollectionViewCell

- (UICollectionViewLayoutAttributes *)preferredLayoutAttributesFittingAttributes:(UICollectionViewLayoutAttributes *)layoutAttributes {
    [self updateConstraintsIfNeeded];
    CGSize size = [self systemLayoutSizeFittingSize:CGSizeMake(1000, 1000)];

    CGRect alteredRect = layoutAttributes.frame;
    alteredRect.size = size;
    layoutAttributes.frame = alteredRect;
    return layoutAttributes;
}

и подклассификация UICollectionView как это

@interface CustomCollectionView ()
@property (nonatomic) BOOL shouldInvalidateLayout;
@end

@implementation CustomCollectionView

- (void)layoutSubviews {
    [super layoutSubviews];
    if (self.shouldInvalidateLayout) {
        [self.collectionViewLayout invalidateLayout];
        self.shouldInvalidateLayout = NO;
    }
}

- (void)reloadData {
    self.shouldInvalidateLayout = YES;
    [super reloadData];
}

@end