Swift: NSRangeException при инициализации UITableViewCells

У меня возникли небольшие проблемы с попыткой заставить мой UITableView работать правильно. Вот как выглядит ошибка:

* Завершение работы приложения из-за необработанного исключения "NSRangeException", причина: "* -[__NSArray0 objectAtIndex:]: индекс 0 за пределами пустого NSArray"

Я сузил проблему до этого фрагмента кода: (строка 2)

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(String(TestCell), forIndexPath: indexPath)
    return cell
}

Полный файл Swift:

class ViewController: UITableViewController {

let closeHeight: CGFloat = 91
let openHeight: CGFloat = 166
var itemHeight = [CGFloat](count: 4, repeatedValue: 91.0)


override func viewDidLoad() {
    super.viewDidLoad()

    tableView.registerClass(TestCell.self, forCellReuseIdentifier: String(TestCell))
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return itemHeight.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier(String(TestCell), forIndexPath: indexPath)
    return cell
}

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return itemHeight[indexPath.row]
}

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let cell = tableView.cellForRowAtIndexPath(indexPath) as! FoldingCell

    var duration = 0.0
    if itemHeight[indexPath.row] == closeHeight { // open cell
        itemHeight[indexPath.row] = openHeight
        cell.selectedAnimation(true, animated: true, completion: nil)
        duration = 0.5
    } else {// close cell
        itemHeight[indexPath.row] = closeHeight
        cell.selectedAnimation(false, animated: true, completion: nil)
        duration = 1.1
    }

    UIView.animateWithDuration(duration, delay: 0, options: .CurveEaseOut, animations: { () -> Void in
        tableView.beginUpdates()
        tableView.endUpdates()
        }, completion: nil)

    }
}

ИЗМЕНИТЬ 1:

class TestCell: FoldingCell {

override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)

    containerView = createContainerView()
    foregroundView = createForegroundView()

    // super class method configure views
    commonInit()
}

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

override func animationDuration(itemIndex: NSInteger, type: AnimationType) -> NSTimeInterval {

    // durations count equal it itemCount
    let durations = [0.33, 0.26, 0.26] // timing animation for each view
    return durations[itemIndex]
}
}

extension TestCell{

func createForegroundView() -> RotatedView{
    let foregroundView = RotatedView(frame: .zero)
    foregroundView.backgroundColor = UIColor.blackColor()
    foregroundView.translatesAutoresizingMaskIntoConstraints = false

    contentView.addSubview(foregroundView)

    foregroundView.topAnchor.constraintEqualToAnchor(foregroundView.superview?.topAnchor, constant: 25)
    foregroundView.leftAnchor.constraintEqualToAnchor(foregroundView.superview?.leftAnchor, constant: 25)
    foregroundView.widthAnchor.constraintEqualToAnchor(foregroundView.superview?.widthAnchor, constant: -50)
    foregroundView.heightAnchor.constraintEqualToConstant(100)

    let topConstraint = foregroundView.constraints[0]
    topConstraint.identifier = "ForegroundViewTop"
    foregroundView.layoutIfNeeded()
    return foregroundView
}

func createContainerView() -> UIView {
    let containerView = UIView(frame: .zero)
    containerView.backgroundColor = UIColor.grayColor()
    containerView.translatesAutoresizingMaskIntoConstraints = false

    contentView.addSubview(containerView)

    containerView.topAnchor.constraintEqualToAnchor(containerView.superview?.topAnchor, constant: 25)
    containerView.leftAnchor.constraintEqualToAnchor(containerView.superview?.leftAnchor, constant: 25)
    containerView.widthAnchor.constraintEqualToAnchor(containerView.superview?.widthAnchor, constant: -50)
    containerView.heightAnchor.constraintEqualToConstant(100)

    let topConstraint = containerView.constraints[0]
    topConstraint.identifier = "ContainerViewTop"
    containerView.layoutIfNeeded()

    return containerView
}
}

К вашему сведению:

Я не использую конструктор интерфейсов по умолчанию, я написал весь код, связанный с графическим интерфейсом, в файле TestCell.swift.

Любые мысли о том, что может быть причиной этой проблемы?

Спасибо!


person Community    schedule 10.08.2016    source источник
comment
Привет, мы можем взглянуть на ваш файл testCell?   -  person Florian Burel    schedule 10.08.2016
comment
@FlorianBurel: Абсолютно :) Взгляните на отредактированный пост.   -  person    schedule 10.08.2016


Ответы (1)


Держу пари, что проблема исходит из:

let topConstraint = containerView.constraints[0]

Проверка размера ограничений может легко доказать это... :)

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

i.e :

containerView.heightAnchor.constraintEqualToConstant(100).active = true
person Florian Burel    schedule 10.08.2016
comment
Из документа Apple: [...] Для вновь созданных ограничений активное свойство по умолчанию НЕТ. Активация или деактивация ограничения вызывает вызовы addConstraint: и removeConstraint: для представления, которое является ближайшим общим предком элементов, управляемых этим ограничением. Используйте это свойство вместо прямого вызова addConstraint: или removeConstraint:. [...] - person Florian Burel; 10.08.2016
comment
О мой Бог. Я забываю добавлять .active = true каждый раз. Вероятно, это и является причиной ошибки, мне нужно выяснить. Хороший глаз! - person ; 10.08.2016