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

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

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


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)
} 

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

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


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.


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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.