Как передать значение пользовательскому UICollectionViewCell?

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

Соответствующий код в контроллере представления:

override func viewDidLoad() {

    self.collectionView!.registerClass(MyCustomCell.self, forCellWithReuseIdentifier: "Cell")

}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! MyCustomCell

    cell.someValue = 5
    cell.imageView.image = UIImage(named: "placeholder.png")

    return cell

}

В пользовательском классе ячеек:

var someValue: Int!
var imageView: UIImageView!

override init(frame: CGRect) {

    super.init(frame: frame)

    imageView = UIImageView(frame: CGRectMake(0, 0, frame.width, frame.height))
    contentView.addSubview(imageView)

    let someValueLabel = UILabel()
    someValueLabel.frame = CGRectMake(0, 75, 200, 30)
    someValueLabel.text = "Value is: \(someValue)"
    self.addSubview(someValueLabel)
}

Изображение успешно передано из UICollectionView, и я могу его отобразить, но «someValue» всегда равно нулю.

Что я делаю неправильно?


person Nitroid    schedule 17.05.2016    source источник
comment
Кроме того, вы не должны называть свое свойство UIImageView imageView. Так как UITableViewCell уже содержит один, использующий это имя. Это может привести к нежелательному эффекту. Может быть, это было исправлено, но я уже столкнулся с некоторыми проблемами. Например, Q: stackoverflow.com/questions/11681273/< /а>   -  person BoilingLime    schedule 19.05.2016


Ответы (3)


Метод init вызывается гораздо раньше, чем вы думаете, — внутри процесса dequeue — когда создается объект ячейки. Частью процесса инициализации является присоединение UIViews, разработанного в раскадровке. Таким образом, это изображение работает, потому что UIImageView уже находится в качестве контейнера во время процесса загрузки раскадровки (NIB), и вы просто устанавливаете его внутреннее свойство изображения позже.

Вы правильно установили значение someValue для всех будущих применений во время рендеринга ячеек и обработки событий. Так, например, если есть обработчик @IBAction, который запускается после отображения ячейки и нажатия на нее, он действительно будет иметь доступ к someValue. Вот где должен быть ваш тестовый отпечаток. Для чего вы в конечном счете используете someValue?

ПОСЛЕДУЮЩИЕ

Итак, это простая ошибка; вам просто нужно установить текстовое значение в cellForRowAtIndexPath. Вам также не нужна копия данных модели в ячейке (т.е. нет необходимости иметь поле someValue в вашей ячейке). Просто настройте пользовательский интерфейс динамически из ваших (правильно разделенных) данных модели:

вместо:

cell.someValue = 5

Вам просто нужно, например:

cell.someValueLabel.text = "\(indexPath.row)" // or where ever you're getting your underlying model data from

Неверно использовать init для всего этого. Единственной обязанностью init для ячеек таблицы является выделение памяти. Ячейка — это полностью динамический временный объект, и все его свойства, отражающие данные приложения, должны быть установлены в методе cellForRowAtIndexPath. Визуальный рендеринг ячейки ожидает завершения метода cellForRowAtIndexPath, поэтому проблем с синхронизацией не возникает.

person BaseZen    schedule 17.05.2016
comment
В реальной версии я пытаюсь передать значение indexPath.item, чтобы я мог внести небольшие изменения во внешний вид ячейки во время инициализации в зависимости от отображаемого содержимого. - person Nitroid; 18.05.2016
comment
Было бы ошибкой вносить изменения во время init. Единственной обязанностью init для ячеек таблицы является выделение памяти. Ячейка — это полностью динамический временный объект, и все его свойства, отражающие данные приложения, должны быть установлены в методе cellForRowAtIndexPath. Визуальный рендеринг ячейки ожидает завершения метода cellForRowAtIndexPath, поэтому проблем с синхронизацией нет. - person BaseZen; 18.05.2016

Метод Init вызывается при создании экземпляра UICollectionView. Вы регистрируете «someValue» в методе инициализации, и это слишком рано. Изображение визуализируется, так как вы работаете непосредственно с ImageView, экземпляр которого уже создан. Попробуйте зарегистрировать imageView.image в методе инициализации, он тоже должен быть нулевым (или, может быть, не нулевым, потому что ячейка используется повторно).

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

var someValue: Int!{
    didSet {
        print("Passed value is: \(newValue)")
    }
}
person lubilis    schedule 17.05.2016

Вы устанавливаете значение someValue после инициализации ячейки.

Вы вызываете print("Passed value is: \(someValue)") во время процесса инициализации.

Установите точку останова в методе инициализации вашего класса ячеек. Вы должны увидеть, как он проходит там, прежде чем присвоить этой переменной значение 5.

person Robert Masen    schedule 17.05.2016