Problem z autoreizacją Ramki uicollectionviewcell contentView w komórce Storyboard prototype (Xcode 6, iOS 8 SDK) występuje tylko w systemie iOS 7

Używam Xcode 6 Beta 3, iOS 8 SDK. Zbuduj docelowy iOS 7.0 za pomocą Swift. Zapoznaj się krok po kroku z moim problemem za pomocą zrzutów ekranu poniżej.

Mam UICollectionView w Storyboard. 1 Prototype UICollectionViewCell, który zawiera 1 etykietę w środku (bez reguły autoresizingu). Fioletowe tło miało oznaczać widok contentView, który jest generowany w trybie runtime przez komórkę. Ten widok zostanie odpowiednio zmieniony na podstawie mojego UICollectionViewLayoutDelegate w końcu, ale nie na iOS 7. Zauważ, że używam Xcode 6 i problem występuje tylko na iOS 7.

Kiedy buduję aplikację na iOS 8. Wszystko w porządku.

Uwaga: Fioletowy to contentView , Niebieski to mój UIButton z zaokrąglonym rogiem.

http://i.stack.imgur.com/uDNDY.png

Jednak na iOS 7 wszystkie podwidywacze wewnątrz komórki nagle kurczą się do klatki (0,0,50,50) i nigdy nie są zgodne z moją regułą Autoresizingu.

http://i.stack.imgur.com/lOZH9.png

Zakładam, że jest to błąd w iOS 8 SDK lub Swift a może Xcode?


Aktualizacja 1: ten problem nadal istnieje w oficjalnym Xcode 6.0.1 ! Najlepiej obejść to, co kocmohabta zasugerował poniżej, ustawiając ramkę w cellForItem komórki(musisz jednak podklasować swoją komórkę). Okazało się, że jest to niezgodność między iOS 8 SDK i iOS 7 (Sprawdź odpowiedź ecotax poniżej cytowaną przez Apple).

Aktualizacja 2: Wklej ten kod na początku cellForItem i powinno be okay:

/** 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 **/
Author: halfer, 2014-07-15

12 answers

ContentView jest uszkodzony. Można go również naprawić w 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]
}
 170
Author: Igor Palaguta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-03 08:46:50

Napotkałem ten sam problem i poprosiłem Apple DTS o pomoc. Ich odpowiedź brzmiała:

W iOS 7 widoki zawartości komórek są skalowane poprzez autoresizację maski. W iOS 8 zostało to zmienione, komórki przestały używać autoresizing masek i rozpoczął rozmiar widoku zawartości w layoutSubviews. Jeśli stalówka jest zakodowana w iOS 8, a następnie dekoduje ją na iOS 7, będziesz miał widok zawartości bez maski autoresizującej i nie inne sposoby, za pomocą których sam rozmiar. Więc jeśli kiedykolwiek zmienisz ramka Widok zawartości komórki nie będzie widoczny.

Aplikacje instalujące się z powrotem na iOS 7 będą musiały to obejść przez zmiana rozmiaru samego widoku zawartości, dodawanie masek automatyzujących lub dodawanie ograniczenia.

Myślę, że oznacza to, że nie jest to błąd w XCode 6, ale niekompatybilność między iOS 8 SDK i iOS 7 SDK, który trafi w przypadku uaktualnienia do Xcode 6, ponieważ automatycznie rozpocznie korzystanie z iOS 8 SDK.

Jak już wcześniej komentowałem, obejście pracy Daniel Plamann opisał prace dla mnie. Te opisane przez Igora Palagutę i Kocmohabtę wyglądają jednak prościej i wydają się mieć sens dając odpowiedź Apple DTS, więc spróbuję później.

 61
Author: ecotax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-17 07:34:06

Napotkałem ten sam problem i mam nadzieję, że Apple naprawi to z następną wersją Xcode. Tymczasem używam obejścia. W mojej podklasie UICollectionViewCell właśnie nadpisałem layoutSubviews i zmieniłem rozmiar contentView ręcznie, jeśli rozmiar różni się od collectionViewCell size.

- (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;
  }
}
 60
Author: Daniel Plamann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-23 07:34:47

Innym rozwiązaniem jest ustawienie rozmiaru contentView i automatyzacji masek w -collectionView:cellForItemAtIndexPath: w następujący sposób:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

     static NSString *cellID = @"CellID";

     UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellID forIndexPath:indexPath];

     // Set contentView's frame and autoresizingMask
     cell.contentView.frame = cell.bounds;
     cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin |UIViewAutoresizingFlexibleTopMargin |UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;

     // Your custom code goes here

     return cell;
}

Działa to również z układem automatycznym, ponieważ maski automatycznej zmiany rozmiaru są tłumaczone na ograniczenia.

 38
Author: KoCMoHaBTa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-03 08:47:50

W Xcode 6.0.1 contentView dla UICollectionViewCell jest uszkodzony dla urządzeń iOS7. Można to również naprawić poprzez dodanie odpowiednich ograniczeń do uicollectionviewcell i jego contentView w metodach awakeFromNib lub 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
Author: SerJ_G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-15 14:06:18

To nie będzie działać poprawnie bez żadnego z innych wymienionych obejść z powodu błędu w Xcode 6 GM z jak Xcode kompiluje pliki xib do formatu nib. Chociaż nie mogę powiedzieć na 100% pewności, że jest to związane z Xcode i nie ma nic wspólnego z uruchomieniem, jestem bardzo pewny - Oto Jak mogę to pokazać:

  1. Zbuduj + Uruchom aplikację w Xcode 5.1.
  2. Przejdź do katalogu aplikacji symulatora i skopiuj skompilowany plik .plik nib dla xib, które masz problemy z.
  3. Build+Run the application in Xcode 6 GM.
  4. zatrzymaj aplikację.
  5. Zastąp .plik nib w nowo zbudowanym folderze symulatora aplikacji zplik nib utworzony przy użyciu Xcode 5.1
  6. Uruchom ponownie aplikację z symulatora, a nie z Xcode.
  7. Twoja komórka załadowana z tego .stalówka powinna działać zgodnie z oczekiwaniami.

Mam nadzieję, że każdy, kto czyta to pytanie, zgłosi się do Apple. Jest to ogromny problem i wymaga rozwiązania przed ostatecznym Xcode uwolnij.

W związku z tym, że w systemie iOS 8 i iOS 7 nie jest to błąd, postanowiłem uaktualnić tę informację, aby potwierdzić różnice w zachowaniu w systemie iOS 8 i iOS 7, ale nie jest to błąd. Mój hack naprawił problem, ponieważ budowanie na iOS 7 dodał maskę autoresizing do widoku treści potrzebne do tego, aby to działało, które Apple już nie dodaje.
 4
Author: Acey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:08

Odpowiedzi w tym poście działają, czego nigdy nie rozumiałem to dlaczego to działa.

Po pierwsze, Są dwie "zasady":

  1. dla widoków tworzonych programowo (np. [UIView new]), właściwość translatesAutoresizingMaskIntoConstraints jest ustawiona na YES
  2. widoki utworzone w interface builder, z włączonym AutoLayout, będą miały właściwość translatesAutoresizingMaskIntoConstraints ustawioną na NO

druga zasada nie dotyczy widoków najwyższego poziomu, dla których nie zdefiniowano ograniczeń. (Ex. na content view)

Patrząc na komórkę scenorysu, zauważ, że komórka nie ma swojej contentView odsłoniętej. Nie" kontrolujemy " contentView, Apple jest.

Zanurz się głęboko w kod źródłowy storyboardu i zobacz, jak zdefiniowana jest komórka contentView: {]}

<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">

Teraz podview komórki (zwróć uwagę na translatesAutoresizingMaskIntoConstraints="NO"):

<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NaT-qJ-npL" userLabel="myCustomLabel">

contentView nie ma translatesAutoresizingMaskIntoConstraints ustawionego na NO. Do tego brakuje definicji layoutu, może dlatego, że @ecotax powiedział .

Jeśli przyjrzymy się contentView, ma ona maskę autoresizującą, ale nie ma dla niej definicji: <autoresizingMask key="autoresizingMask"/>

Są więc dwa wnioski:

  1. contentView translatesAutoresizingMaskIntoConstraints jest ustawione na YES.
  2. contentView brak definicji układu.
To prowadzi nas do dwóch rozwiązań, o których mówiono.

Można ręcznie ustawić maski autoresizujące w awakeFromNib:

self.contentView.frame = cell.bounds;
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

Lub możesz ustawić contentView translatesAutoresizingMaskIntoConstraints do NO w awakeFromNib i zdefiniować ograniczenia w - (void)updateConstraints.

 4
Author: kgaidis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:08

To jest szybka wersja odpowiedzi @ Igor, która została zaakceptowana i dzięki za miłą odpowiedź kolego.

Najpierw wejdź do swojej podklasy UICollectionViewCell i wklej poniższy kod, który znajduje się wewnątrz klasy.

override func awakeFromNib() {
    super.awakeFromNib()
    self.contentView.frame = self.bounds
    self.contentView.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
}

Przy okazji używam Xcode 7.3.1 i Swift 2.3. Rozwiązanie jest testowane na iOS 9.3, który działa bez zarzutu.

Dzięki, Mam nadzieję, że to pomogło.
 4
Author: onCompletion,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-15 18:59:58

W języku swift umieść następujący kod w podklasie komórki widoku kolekcji:

override var bounds: CGRect {
  didSet {
    // Fix autolayout constraints broken in Xcode 6 GM + iOS 7.1
    self.contentView.frame = bounds
  }
}
 2
Author: Ian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-16 19:08:54

Odkryłem, że istnieją również problemy z rozmiarem contentView w iOS 8. Ma tendencję do układania się bardzo późno w cyklu, co może powodować tymczasowe konflikty ograniczeń. Aby to rozwiązać, dodałem następującą metodę w kategorii 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
}

Metoda ta powinna być wywołana po usunięciu komórki.

 1
Author: phatmann,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-07 16:16:13

Naprawiłem robiąc to:

override func layoutSubviews() {
   contentView.superview?.frame = bounds
   super.layoutSubviews()
}

Zobacz: tutaj

 1
Author: Serluca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:21

Upewnij się tylko, że zaznaczono pole wyboru "Autoresize subviews" w nib dla tej komórki widoku kolekcji. Będzie działać dobrze zarówno na iOS 8, jak i iOS 7.

 -1
Author: Deepak G M,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-20 13:40:57