Класс регистра UICollectionViewCell терпит неудачу, но регистр работает с nib

Создание пользовательского UICollectionViewCell для моего UICollectionViewController, он работает, регистрируя nib; однако, не удается зарегистрировать класс.

Использование registerClass() - fail

Регистрирование по классу кажется правильным - оно строит, но генерирует исключение во время выполнения, освобождая дополнительные элементы из UIView. Без ссылок на торговые точки он работает; однако в представлении коллекции нет ячеек.

collectionView?.registerClass(MyCollectionViewCell.self, 
                              forCellWithReuseIdentifier: "myCell")

Ясно, что представление не загружено; однако, я думаю, что настройка пользовательского класса ячейки обеспечит необходимую связь.

Использование registerNib() - работает

Регистрация с помощью nib-работ, что имеет смысл, поскольку она явно загружает представление.

let nib = UINib(nibName: "MyCollectionViewCell", bundle: nil)
collectionView?.registerNib(nib, forCellWithReuseIdentifier: "myCell")

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

Пример проекта

Изоляция проблемы в примере проекта, ниже - виды и код для репликации; или этот проект доступен в GitHub.

Main.storyboard

Мой главный контроллер начального представления раскадровки является UICollectionViewController подклассом как MyCollectionViewController:

UICollectionViewController

MyCollectionViewController.swift

Показывает как регистрацию по nib, так и по классу:

import UIKit

class MyCollectionViewController: UICollectionViewController {

    var data = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()

        data = ["a", "b", "c"]

        // This works, by nib
        let nib = UINib(nibName: "MyCollectionViewCell", bundle: nil)
        collectionView?.registerNib(nib, forCellWithReuseIdentifier: "myCell")

        // This fails, by class
        //collectionView?.registerClass(MyCollectionViewCell.self, forCellWithReuseIdentifier: "myCell")
    }

    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return data.count
    }

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("myCell", forIndexPath: indexPath) as! MyCollectionViewCell

        cell.title.text = data[indexPath.row]

        return cell
    }

}

MyCollectionViewCell.xib

Вид является UICollectionViewCell подклассом как MyCollectionViewCell с UILabel:

MyCollectionViewCell

В моем nib идентификатор коллекционного повторного просмотра был установлен: myCell:

MyCollectionViewCell-identifier

MyCollectionViewCell.swift

Определяет класс и имеет IBOutlet для метки:

import UIKit

class MyCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var title: UILabel!

}

Используя nib, выполнение появляется как:

iphone-4s

Почему я не могу зарегистрировать UICollectionViewCell по классу?

Кроме того, я немного неясен относительно того, должна ли ячейка прототипа оставаться на главном контроллере представления коллекции раскадровки. Там я не определил идентификатор многократного использования.

Ответ 1

Я вижу эту ссылку Обзор коллекции >

Если класс ячейки был написан в коде, регистрация выполняется с использованием метода registerClass: UICollectionView. Например: [self.myCollectionView registerClass: [Класс MyCollectionViewCell] forCellWithReuseIdentifier: @ "MYCELL" ]; В случае, если ячейка содержится в файле NIB Interface Builder, вместо этого используется метод registerNib:

Итак, ваша ячейка коллекции создаёт с помощью nib, вы должны зарегистрироваться в nib. Если ваша ячейка полностью написана в коде, вам потребуется зарегистрироваться в классе.

Надеюсь на эту помощь.

Ответ 2

Собственно, если вы зарегистрируете класс в раскадровке и дадите ему идентификатор повторного использования, то вы не должны регистрировать его класс или код в коде.

Ответ 3

Это не коллекция, которая здесь не работает. Пользовательский класс содержит ярлык, который неявно разворачивается, как опция,

@IBOutlet weak var title: UILabel!

И в этом причина неудачи. Где вы его создаете? И ваши методы datasource вызываются так, как это,

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("myCell", forIndexPath: indexPath) as! MyCollectionViewCell

    cell.title.text = data[indexPath.row]

    return cell
}

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

Инициализируйте свою метку внутри метода collectionView initWithFrame:, если вы используете его в коде, который должен быть исправлен.

Добавьте этот код в свой подкласс класса при использовании в коде,

class MyCollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var title: UILabel!

    override init(frame: CGRect) {
        super.init(frame: frame)
        let title = UILabel(frame: CGRectZero)
        title.translatesAutoresizingMaskIntoConstraints = false;
        contentView.addSubview(title)
        self.title = title

        title.topAnchor.constraintEqualToAnchor(contentView.topAnchor).active = true
        title.leftAnchor.constraintEqualToAnchor(contentView.leftAnchor).active = true
        self.backgroundColor = UIColor.redColor()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

Ответ 4

если вы определяете ячейку из файла nib, система выберет nib файл для создания экземпляра ячейки. Если не определить какой-либо файл nib (полностью поддерживаемый кодом), ячейка должна быть init с помощью

- initWithStyle:reuseIdentifier:

метод. Когда вы используете

- dequeueReusableCellWithIdentifier:

метод - awakeFromNib будет вызываться, если вы используете nib для сохранения представления; else

- initWithStyle:reuseIdentifier:

будет вызываться.