Создание единого .xib для разных классов UITableViewCell

Я столкнулся с проблемой

У меня есть файл NNVerticalStackTableViewCell.xib и его соответствующий файл NNVerticalStackTableViewCell.swift.

Код для NNVerticalStackTableViewCell.swift файла

class NNVerticalStackTableViewCell: UITableViewCell
{
    //MARK: Outlets
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var verticalStack: NNVerticalStackView!

    //MARK: Internal Properties
    var titleString : String?
        {
        set{
            self.titleLabel.text = newValue
        }
        get{
            return self.titleLabel.text
        }
    }

    //MARK: View Lifecycle Methods
    override func awakeFromNib()
    {
        super.awakeFromNib()
        self.titleLabel.text = nil
    }

    //MARK: Internal Methods
    func addViewsInVerticalStack(viewsArray : [UIView])
    {
        for view in viewsArray
        {
            self.verticalStack.insertStackItem(view)
        }
    }
}

Интерфейс для файла NNVerticalStackTableViewCell.xib

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

с class name как: NNVerticalStackTableViewCell и cell identifier как: NNVerticalStackTableViewCell

Теперь я создал подкласс NNVerticalStackTableViewCell как:

class NNPropertiesUnderProjectTableViewCell: NNVerticalStackTableViewCell
{
    //MARK: Internal Properties
    var completionHandler : ((NNSearchPreference) -> Void)?

    //MARK: Internal Methods
    func configureCell(_ propertiesUnderProjectArray : [[String : Any]])
    {
        var viewsArray = [UIView]()
        for dict in propertiesUnderProjectArray
        {
            let elementView = NNPropertiesUnderProjectElementView.loadFromNib()
            elementView?.configureViewWith(buttonTitleString: dict["displayString"] as! String, searchPreference: dict["searchPreference"] as! NNSearchPreference, completionHandler: {[weak self] (searchPreference) in
                if let handler = self?.completionHandler
                {
                    handler(searchPreference)
                }
                })
            viewsArray.addObject(elementView)
        }
        self.addViewsInVerticalStack(viewsArray: viewsArray)
    }
}

Теперь я хочу использовать класс NNPropertiesUnderProjectTableViewCell с интерфейсом NNVerticalStackTableViewCell.xib.

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

В моем ViewController я зарегистрировал NNVerticalStackTableViewCell.xib, а затем создал ячейку как:

self.tableView.register(UINib(nibName: "NNVerticalStackTableViewCell"), forCellReuseIdentifier: "NNVerticalStackTableViewCell")


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
            let propertiesUnderProjectCell = tableView.dequeueReusableCell(withIdentifier: "NNVerticalStackTableViewCell", for: indexPath as IndexPath) as! NNPropertiesUnderProjectTableViewCell
    }

Но я получаю исключение:

Could not cast value of type 'NNVerticalStackTableViewCell' (0x100945878) to 'NNPropertiesUnderProjectTableViewCell' (0x100949330).

Кто-нибудь может предложить, как решить проблему. Я хочу использовать одиночный .xib и не хочу повторять код.

Ответ 1

Вы можете, но вместо использования UITableViewCell используйте аналогичный UIView

Создайте xib для представления содержимого ячейки, дайте ему класс (например, CellView). В каждом классе ячейки получите CellView с помощью loadNibNamed и установите его как представление содержимого ячейки, затем вы можете свободно изменять свойство CellView и использовать его в качестве представления содержимого класса ячейки

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

Ответ 2

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

Здесь вы можете выполнить репликацию NNVerticalStackTableViewCell.xib и сохранить NNVerticalStackTableViewCell.swift в качестве базового класса.

затем создайте что-то вроде NNPropertiesUnderProjectTableViewCell.xib, где он содержит то же представление, что и до NNVerticalStackTableViewCell.xib, с добавленными элементами управления. Затем подклассируем его до NNPropertiesUnderProjectTableViewCell.swift с уникальным идентификатором: NNPropertiesUnderProjectTableViewCell.

в котором NNPropertiesUnderProjectTableViewCell является подклассом NNVerticalStackTableViewCell.

Теперь просто добавьте дополнительные элементы управления, уникальные для класса NNPropertiesUnderProjectTableViewCell.

Ответ 3

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

Предложение от @Tj3n является хорошим, извлечь общую часть в многоразовое представление и в вашей инициализации суперкласса создать экземпляр этого представления и добавить его. Теперь, когда вы создаете экземпляр подкласса и называет super, общий элемент будет инициализироваться и использоваться подклассом.

Другими словами, используйте композицию для достижения своей цели, а не наследования.

Ответ 4

Вы можете сделать это, если хотите использовать tableViewCell.xib за несколько раз. Сначала перейдите в файл и создайте новый файл (Cocoa Touch Class).

Класс CocoaTouch

Создать файл TableViewCell с .xib

TableViewCell

Теперь просто создайте свой собственный дизайн ячеек

Дизайн

Теперь добавьте этот код в свой файл TableViewCell.swift

Изображение

Теперь просто добавьте идентификатор в свой TableView Cell, как это (где вы хотите добавить этот пользовательский TableviewCell)

cell

Теперь просто возьмите его как свою ячейку. Вот как...

Таблица

И Бинго Вы получили это.

Теперь просто добавьте ячейку как! TableViewCell в любом файле TableViewController (у вас одинаковые результаты с тем же дизайном).

OutPut1

Здесь нажмите "Сначала" (Load First TableViewController)

FirstTable

Вкл. второй щелчок (Load Second TableViewController)

SecondTable View

Ответ 5

NNPropertiesUnderProjectTableViewCell не регистрируется для Cellidentifier.