Проблема автосохранения календаря содержимого UICollectionViewCell в ячейке прототипа Storyboard (Xcode 6, iOS 8 SDK) происходит при запуске только на iOS 7
Я использую Xcode 6 Beta 3, iOS 8 SDK. Создайте целевой iOS 7.0 с помощью Swift. Пожалуйста, обратитесь к моей проблеме шаг за шагом со скриншотами ниже.
У меня есть UICollectionView в раскадровке. 1 Prototype UICollectionViewCell, который содержит 1 ярлык в центре (без правила автореализации). Фиолетовый фон состоял в том, чтобы отметить contentView, который создается во время выполнения Cell. В конечном итоге это представление будет правильно изменено на моем UICollectionViewLayoutDelegate, но не на iOS 7. Обратите внимание, что я использую Xcode 6, и проблема возникает только на iOS 7.
Когда я создаю приложение на iOS 8. Все в порядке.
Примечание. Фиолетовый - это contentView, синий - это мой UIButton с закругленным углом.
Однако на iOS 7 все подвид внутри ячейки внезапно сжимаются до кадра (0,0,50,50) и больше не соответствуют моему правилу авторезистировки.
Я предполагаю, что это ошибка в iOS 8 SDK или Swift или, возможно, Xcode?
Обновление 1: Эта проблема все еще существует в официальном Xcode 6.0.1! Лучшая работа вокруг - это то, что предлагает KoCMoHaBTa ниже, установив фрейм в cellForItem ячейки (вы должны подклассифицировать свою ячейку, хотя). Оказалось, что это несовместимость между iOS 8 SDK и iOS 7 (см. Ниже приведенный ниже ответ на экотакс от Apple).
Обновление 2:
Вставьте этот код в начало cellForItem, и все должно быть в порядке:
/** Xcode 6 on iOS 7 hot fix **/
cell.contentView.frame = cell.bounds;
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
/** End of Xcode 6 on iOS 7 hot fix **/
Ответы
Ответ 1
contentView нарушен. Он также может быть зафиксирован в awakeFromNib
ObjC:
-(void)awakeFromNib
{
[super awakeFromNib];
self.contentView.frame = self.bounds;
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
Swift3:
override func awakeFromNib() {
super.awakeFromNib()
self.contentView.frame = self.bounds
self.contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
Ответ 2
Я столкнулся с той же проблемой и попросил Apple DTS получить помощь. Их ответ был:
В iOS 7 просмотры содержимого ячеек сами по себе определяют путем авторезистирования маски. В iOS 8 это было изменено, ячейки перестали использовать авторезистировать маски и начать определение содержимого в layoutSubviews. Если нить кодируется в iOS 8, а затем декодирует его на iOS 7, у вас будет просмотр содержимого без маски авторезистации и нет другие средства, с помощью которых можно самим определять размер. Поэтому, если вы когда-либо меняете рамку ячейки, представление содержимого не будет следовать.
Приложения, развертывающие обратно в iOS 7, должны будут обойти это определение размера содержимого, добавление авторезистирующих масок или добавление ограничения.
Я предполагаю, что это означает, что это не ошибка в XCode 6, а несовместимость между iOS 8 SDK и iOS 7 SDK, которая поразит вас, если вы перейдете на Xcode 6, потому что он автоматически начнет использовать iOS 8 SDK.
Как я уже говорил, обходной путь Даниэля Пламана описан для меня. Те, о которых рассказывают Игорь Палагута и KoCMoHaBTa, выглядят более просто и, похоже, имеют смысл дать ответ Apple DTS, поэтому я попробую их позже.
Ответ 3
Я столкнулся с той же проблемой и надеюсь, что Apple исправит это со следующей версией Xcode. Тем временем я использую обходной путь. В моем подклассе UICollectionViewCell
я только что переопределил layoutSubviews
и изменил размер содержимогоView вручную, если размер отличается от размера collectionViewCell
.
- (void)layoutSubviews
{
[super layoutSubviews];
BOOL contentViewIsAutoresized = CGSizeEqualToSize(self.frame.size, self.contentView.frame.size);
if( !contentViewIsAutoresized) {
CGRect contentViewFrame = self.contentView.frame;
contentViewFrame.size = self.frame.size;
self.contentView.frame = contentViewFrame;
}
}
Ответ 4
Другим решением является установка размера contentView и масок авторазрешения в -collectionView: cellForItemAtIndexPath:
например:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = @"CellID";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];
//set contentView frame and autoresizingMask
cell.contentView.frame = cell.bounds;
cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
//You custom code goes here
return cell;
}
Это также работает с автоматической компоновкой, поскольку маски автоматического изменения размера преобразуются в ограничения.
Ответ 5
В Xcode 6.0.1 contentView для UICollectionViewCell нарушается для устройств iOS7.
Он также может быть исправлен путем добавления правильных ограничений для UICollectionViewCell и его contentView в awakeFromNib или init.
UIView *cellContentView = self.contentView;
cellContentView.translatesAutoresizingMaskIntoConstraints = NO;
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[cellContentView]|"
options:0
metrics:0
views:NSDictionaryOfVariableBindings(cellContentView)]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[cellContentView]|"
options:0
metrics:0
views:NSDictionaryOfVariableBindings(cellContentView)]];
Ответ 6
Это не будет работать корректно без каких-либо других упомянутых обходных решений из-за ошибки в Xcode 6 GM с тем, как Xcode компилирует xib файлы в формат nib. Хотя я не могу сказать на 100% уверенность, что это связано с Xcode и не связано со временем выполнения, я очень уверен в этом: вот как я могу это показать:
- Сборка + Запуск приложения в Xcode 5.1.
- Перейдите в каталог приложения simulator и скопируйте скомпилированный .nib файл для xib, с которым у вас возникли проблемы.
- Build + Запустите приложение в Xcode 6 GM.
- Остановить приложение.
- Замените файл .nib во вновь созданной папке симулятора приложения с файлом .nib, созданным с помощью Xcode 5.1
- Перезапустите приложение из симулятора, а не с Xcode.
- Ваша ячейка, загруженная из этого .nib, должна работать как ожидалось.
Я надеюсь, что каждый, кто прочитает этот вопрос, подаст радар с Apple. Это ОГРОМНАЯ проблема и требует решения перед окончательной версией Xcode.
Изменить: В свете ecotax post, я просто хотел обновить это, чтобы сказать, что теперь подтверждены различия в поведении между зданием в iOS 8 и iOS 7, но не Жук. Мой взлом исправил проблему, потому что построение на iOS 7 добавило маску авторезистирования в представление контента, необходимое для выполнения этой работы, которое Apple больше не добавляет.
Ответ 7
Ответы в этой статье работают, я никогда не понимал почему работает.
Во-первых, существует два "правила":
- Для представлений, созданных программно (пример
[UIView new]
), для свойства translatesAutoresizingMaskIntoConstraints
установлено значение YES
- Представления, созданные в конструкторе интерфейса, с включенным автозапуском, будут иметь свойство
translatesAutoresizingMaskIntoConstraints
, установленное в NO
Второе правило, похоже, не относится к представлениям верхнего уровня, для которых вы не определяете ограничения. (Пример содержимого)
При просмотре ячейки раскадровки обратите внимание на то, что у ячейки нет ее contentView
. Мы не "контролируем" contentView
, Apple.
Глубоко погрузитесь в исходный код раскадровки и посмотрите, как определяется ячейка contentView
:
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
Теперь подкатегории ячейки (обратите внимание на translatesAutoresizingMaskIntoConstraints="NO"
):
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NaT-qJ-npL" userLabel="myCustomLabel">
contentView
не имеет translatesAutoresizingMaskIntoConstraints
, установленного в NO
. Кроме того, ему не хватает определения макета, возможно, из-за чего @ecotax сказал.
Если мы посмотрим на contentView
, у него есть авторезистирующая маска, но нет определения для нее:
<autoresizingMask key="autoresizingMask"/>
Итак, есть два вывода:
-
contentView
translatesAutoresizingMaskIntoConstraints
установлен на YES
.
-
contentView
отсутствует определение макета.
Это приводит нас к двум решениям, о которых говорили.
Маски авторезистировки можно настроить вручную в awakeFromNib
:
self.contentView.frame = cell.bounds;
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
Или вы можете установить contentView
translatesAutoresizingMaskIntoConstraints
в NO
в awakeFromNib
и определить ограничения в - (void)updateConstraints
.
Ответ 8
Это сводная версия ответа @Igor, которая принимается и благодарит за ваш приятный ответ.
Сначала Перейдите к подклассу UICollectionViewCell
и вставьте следующий код, как внутри класса.
override func awakeFromNib() {
super.awakeFromNib()
self.contentView.frame = self.bounds
self.contentView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
}
Кстати, я использую Xcode 7.3.1 и Swift 2.3. Решение протестировано на iOS 9.3, которое работает безупречно.
Спасибо, надеюсь, это помогло.
Ответ 9
В swift поместите следующий код в подкласс ячейки представления коллекции:
override var bounds : CGRect {
didSet {
// Fix autolayout constraints broken in Xcode 6 GM + iOS 7.1
self.contentView.frame = bounds
}
}
Ответ 10
Я обнаружил, что есть проблемы с размером contentView
в iOS 8. Он, как правило, слишком поздно выкладывается в цикле, что может привести к конфликтам временных ограничений. Чтобы решить эту проблему, я добавил следующий метод в категорию UICollectionViewCell
:
- (void)fixupContentView
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80100
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
if (NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1) {
self.contentView.frame = self.bounds;
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
} else {
[self layoutIfNeeded];
}
#endif
#endif
}
Этот метод следует вызывать после удаления ячейки.
Ответ 11
Я исправил это:
override func layoutSubviews() {
contentView.superview?.frame = bounds
super.layoutSubviews()
}
см. здесь
Ответ 12
Просто убедитесь, что вы установите флажок "Autoresize subviews" в nib для этой ячейки представления коллекции. Он отлично работает как на iOS 8, так и на iOS 7.