CollectionView sizeForItemAtIndexPath никогда не вызывается

96

Это сводит меня с ума! У меня есть UICollectionViewController, как показано ниже:

class PhrasesCompactCollectionViewController: UICollectionViewController

Вызываются numberOfSections и cellForItemAt, но sizeForItemAtIndexPath никогда не вызывается. Я использую точно такой же код в другом месте, и он работает правильно. Я использую Xcode 8 Beta 6.

func collectionView(collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAtIndexPath indexPath:  NSIndexPath) -> CGSize {

        return CGSize(width: 120, height:120) 
    }
Джон Доу
источник

Ответы:

255

Вам необходимо указать, что вы реализуете протокол UICollectionViewDelegateFlowLayoutв своем объявлении класса.

class PhrasesCompactCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout

Алмас
источник
11
Я сделал это, но он все еще не называется. :(
Ван Ду Тран
58

В Swift 3+ используйте этот метод:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width:(collectionView.frame.height-90)/2, height: 100)
}

Убедитесь, что ваш класс соответствует требованиям Delegate

  • UICollectionViewDelegate

  • UICollectionViewDelegateFlowLayout

Шив Кумар
источник
4
Это избыточно для соблюдения, UICollectionViewDelegateкак это уже делает UICollectionViewController.
Ван Дю Тран,
3
@VanDuTran Не лишним будет сказать, что это необходимо, потому что быть UICollectionViewController не требуется ...
Майкл Хадсон,
Я думаю, вы имели в виду, что Viewcontroller не является представлением коллекции, может быть UICollectionViewDelegate.
ScottyBlades
1
UICollectionViewDelegateFlowLayout наследуется от UICollectionViewDelegate, поэтому просто реализуйте UICollectionViewDelegateFlowLayout
evya
49

У меня такая же проблема. Единственное, что мне помогло, - это установить «Расчетный размер» для размера ячейки в инспекторе размера коллекции «Нет».

введите описание изображения здесь

Zenman C
источник
9
Ты спас мне день, приятель, ты герой
Асиф Али
1
Как-то все другие ответы на все другие сообщения об использовании sizeForItemAtне упоминали об этом. Очень полезно.
JCutting8,
Это безумие!!!! Я тестировал симулятор iPhone 5 с версией iOS 10.3.1, и метод был вызван. на iPhone 5s симулятор с версией 10.3.1 метод не вызывается !!! Я изменил расчетный размер на «Нет». Его начали называть на iPhone 5s. WT WT WT
хасан
Большое спасибо! Моя коллекция с пользовательскими настройками sizeForItemAtработала хорошо до Xcode 11.4, когда внезапно ячейки оказались неправильной ширины. Пробовал кучу вещей, и это, наконец, сработало.
Филип
Вы сэкономили мне время. Большое спасибо.
Шахбаз Акрам
17

Swift 5

Все эти шаги обязательны :

  1. Соответствует UICollectionViewDelegateFlowLayout <== Абсолютно необходимо !!
  2. и чтобы UICollectionViewDelegate, UICollectionViewDataSource
  3. Установите их в viewDidLoad: collectionView.delegate = selfиcollectionView.dataSource = self
  4. Установите для размера оценки значение None в Interface Builder
  5. Убедитесь, что следующий метод имеет sizeForItemAt, а не sizeForItemAtIndexPath

в качестве :

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
{
    return CGSize(width: 100, height:100)
} 
Xys
источник
3
Оценить размер до «Нет» - спаси день!
Джо Халленбек,
Примите этот ответ, он правильный!
NickCoder
15

Swift 3

Чтобы установить размер ячейки UICollectionView, вам необходимо создать и настроить объект UICollectionViewFlowLayout. Настройте свойства и установите этот объект макета в объект UICollectionView.

Измените ячейки cellheight и cellWidth в соответствии с вашими требованиями (желаемую высоту и ширину ячейки).

override func viewDidLoad() {
    super.viewDidLoad()

    let cellWidth : CGFloat = myCollectionView.frame.size.width / 4.0
    let cellheight : CGFloat = myCollectionView.frame.size.height - 2.0
    let cellSize = CGSize(width: cellWidth , height:cellheight)

    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .vertical //.horizontal
    layout.itemSize = cellSize
    layout.sectionInset = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1)
    layout.minimumLineSpacing = 1.0
    layout.minimumInteritemSpacing = 1.0
    myCollectionView.setCollectionViewLayout(layout, animated: true)

    myCollectionView.reloadData()
}

Убедитесь, что если вы добавили метод sizeForItemAt indexPath, тогда необходимо УДАЛИТЬ метод ...

Удалить ниже метод

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

}
Гаурав Рами
источник
12
Чем это полезно?
almas
1
Алмас, Это будет полезно для установки пользовательского размера ячейки UICollectionViewCell ... Существуют переменные cellWidth и cellHeight, в которых вы можете определять свои собственные значения ... А также "layout.sectionInset", "layout.minimumLineSpacing" и "layout .minimumInteritemSpacing ", эти переменные также имеют значение для размера UICollectionViewCell ..
Горав Рами,
2
Это работает, только если все ячейки одинакового размера. Правильный ответ приведен ниже
JeffN
это для изменения размера UICollectionView, но не ячейки внутри представления
Async
Это не ответ на вопрос, почему не вызывается метод делегата
Зив Кестен
6

Первому классу необходимо подтвердить UICollectionViewDelegateFlowLayout. Затем вам нужно написать следующий код в viewDidLoad ():

// Чтобы указать UICollectionView использовать методы UICollectionViewDelegateFlowLayout вашего UIViewController

collectionView.delegate = self

// Если вы хотите установить свой собственный макет потока представления коллекции

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical //depending upon direction of collection view

self.collectionView?.setCollectionViewLayout(layout, animated: true)

Используя этот метод кода UICollectionViewDelegateFlowLayout

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize

будет вызван, вы можете установить размер в этом методе.

HS Progr
источник
4

Если нет ответа, вам нужно проверить три вещи:

  1. Реализуйте FlowLayout Delegate: class MyController: UICollectionViewController, UICollectionViewDelegateFlowLayout

  2. Используйте метод размера элемента для Swift 3.0+: func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(width: (collectionView.frame.width / 3) - 1, height: collectionView.frame.width) }

  3. Выберите Estimate size = Noneв Inspect элемент UICollectionView.

Manish
источник
2

У меня была такая же проблема, и ничто не могло ее исправить. У меня было желтое предупреждение о том, что нужно сделать его закрытым, потому что оно близко к другой функции, определенной делегатом макета. Для меня это было исправлено:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize

Обратите внимание на разницу между sizeForItemAtIndexPath и sizeForItemAt.

Я вырывал себе волосы в течение нескольких дней, пытаясь понять это, и, наконец, это сработало. Ниже я включу все свои функции, чтобы показать вам, как я также «спрятал» ячейку, сделав высоту равной 0.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let findIndex = labelArray.index(of: "\(labelArray[indexPath.row])")
    let screenSize = UIScreen.main.bounds
    let screenWidth = screenSize.width

    if (findIndex! % 2 == 0){
        // Even index, show cell
        return CGSize(width: screenWidth, height: 246)
    }
    else {
        return CGSize(width: screenWidth, height: 0)
    }
}
Стивен Рейнс
источник
1

Убедитесь, что вы поместили это в viewDidLoad ()

collectionView.delegate = self
Азам
источник
0

У меня была эта проблема вчера вечером. В конце концов решил это в полночь, когда я понял, что метод didSelectItemAtIndex не был закрыт закрывающей скобкой "}"

Я добавил закрывающую скобку в самом низу класса, когда ее спросила ошибка компиляции. Таким образом, все методы, указанные ниже, «didSelectItemAtIndex» были внутри этого метода.

Публикация здесь на случай, если кто-то еще потратит на это 4 часа своих вечеров :-(

Чарли Селигман
источник
0

Моя проблема заключалась в том, что у меня был объект UICollectionViewDataSource, созданный как локальная переменная. Поэтому, если вы инициализируете свой объект dataSource вручную в коде, обязательно сохраните его как глобальную переменную.

Петр Дарчин
источник
0

Используйте этот метод

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

}

Вместо того

private func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

}
Абдул Малик Аман
источник
0

Просто добавьте: UICollectionViewDelegateFlowLayout

class YourClass: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {}
Музаммил
источник
-12

Для меня (в Swift 3.1) метод должен быть объявлен публичным следующим образом:

    public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
       return CGSize()
    }

Не забудьте сделать это общедоступным .

Оливер Эйххорн
источник
publicэто то, что вы используете, чтобы сделать свой код доступным между фреймворками и модулями.
ScottyBlades