Подтвердить что ты не робот

UICollectionView должен быть инициализирован параметром макета не-nil

Я новичок в UICollectionView, и я следую учебнику, которое я нашел в Интернете, но я застрял в ошибке, которую я не могу понять. Здесь немного контекста.

В отладчике я вижу, что происходит следующее:

  • numberOfSectionsInCollectionView: вызывается и я возвращаю 1
  • collectionView:numberOfItemsInSection: вызывается, и я возвращаю размер модели (20)
  • collectionView:layout:sizeForItemAtIndexPath: вызывается один раз для каждого элемента в модели
  • collectionView:layout:insetForSectionAtIndex: называется
  • collectionView:cellForItemAtIndexPath: вызывается и он сбой в этой строке...

    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyCell" forIndexPath:indexPath];
    

с этой ошибкой...

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter'

Когда я приостанавливаю выполнение в этой строке и проверяю консоль, кажется, что есть макет...

(lldb) po collectionView.collectionViewLayout
(UICollectionViewLayout *) $4 = 0x07180fd0 <UICollectionViewFlowLayout: 0x7180fd0>

UICollectionView является частью единственной сцены в раскадровке. В viewController.m нет других UICollectionView, созданных любыми способами.

Есть ли у кого-нибудь идеи?

4b9b3361

Ответ 1

Как оказалось, проблема была в registerClass:. У меня было это:

[self.collectionView registerClass:[UICollectionView class] 
        forCellWithReuseIdentifier:@"MyCell"];

но это должно быть так:

[self.collectionView registerClass:[UICollectionViewCell class] 
        forCellWithReuseIdentifier:@"MyCell"];

Таким образом, метод dequeue создавал UICollectionView вместо UICollectionViewCell.

Ответ 2

Это сработало для меня:

UICollectionViewFlowLayout *aFlowLayout = [[UICollectionViewFlowLayout alloc] init];
    [aFlowLayout setItemSize:CGSizeMake(200, 140)];
    [aFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
myCollectionViewController = [[MyCollectionViewController alloc]initWithCollectionViewLayout:flowLayout];

Если вы произвольно создаете UICollectionView, требуется макет.

Ответ 3

Если вы создаете программный контроллер коллекций в UICollectionViewController, убедитесь, что метод UICollectionViewController init использует [super initWithCollectionViewLayout] вместо [super init], например:

-(id) initWithImages:(NSArray *)pImages {
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
    [layout setMinimumInteritemSpacing:0.0f];
    [layout setMinimumLineSpacing:0.0f];
    layout.scrollDirection = UICollectionViewScrollDirectionVertical;
    if (self = [super initWithCollectionViewLayout:layout]) {
        _images= [[NSArray alloc] initWithArray:pImages];
    }
    return self;
}

От: Ссылка на класс UICollectionViewController: обзор

Ответ 4

У меня такая же проблема, и моя решена с помощью

UICollectionViewFlowLayout *myLayout = [[UICollectionViewFlowLayout alloc]init];
[myLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
[myLayout setMinimumInteritemSpacing:0.0f];
[myLayout setMinimumLineSpacing:0.0f];
UICollectionView *myCollectionView = [[UICollectionView alloc]initWithFrame:viewfame collectionViewLayout:myLayout];

вместо

UICollectionView *myCollectionView = [[UICollectionView alloc]initWithFrame:self.view.frame];
[myLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
[myLayout setMinimumInteritemSpacing:0.0f];
[myLayout setMinimumLineSpacing:0.0f];
[myCollectionView setCollectionViewLayout:myLayout];

Ответ 5

Я столкнулся с этой проблемой при возврате объекта UICollectionViewLayout с ItemSize равным self.view.bounds перед инициализацией представления.

Ответ 6

Если ваш класс Inherit от UICollectionViewController или вы создаете программный код UICollectionView, то при нажатии класса вы можете установить collectionViewLayout, как показано ниже

let homeViewController = HomeViewContoller(collectionViewLayout:UICollectionViewLayout())