Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating single .xib for different UITableViewCell classes

I am facing a problem

I have a NNVerticalStackTableViewCell.xib file and its corresponding NNVerticalStackTableViewCell.swift file.

Code for NNVerticalStackTableViewCell.swift file

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

Interface for NNVerticalStackTableViewCell.xib file

enter image description here

with class name as : NNVerticalStackTableViewCell and cell identifier as : NNVerticalStackTableViewCell

Now I created a subclass of NNVerticalStackTableViewCell as:

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

Now what I want to do is use NNPropertiesUnderProjectTableViewCell class with NNVerticalStackTableViewCell.xib interface.

Similar to NNPropertiesUnderProjectTableViewCell class I have many other classes that uses the same interface as NNVerticalStackTableViewCell.xib and customize it accordingly.

In my ViewController, I registered NNVerticalStackTableViewCell.xib and then creating the cell as:

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
    }

But, I am getting the exception :

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

Can anyone please suggest how to solve the problem. I want to use single .xib and do not want to repeat the code.

like image 986
PGDev Avatar asked Nov 09 '16 07:11

PGDev


4 Answers

You can, but, instead of using the UITableViewCell, use similar UIView

Create a xib for the cell content view, give it a class (like CellView). In each cell class, get the CellView with loadNibNamed and set it as the cell content view, then you can freely change the property of the CellView and use it as other cell class's content view

Maybe there's better solution, but this is how i do it for similar looking UIViewController, you might also try cell xib without class set in storyboard and try to load it and see if the error still persist or not

like image 51
Tj3n Avatar answered Oct 22 '22 01:10

Tj3n


You can't do that as the registerNib: expect the same instance of the exact registered view.

From here you can do is replicate NNVerticalStackTableViewCell.xib and retain NNVerticalStackTableViewCell.swift as your base class.

then create something like NNPropertiesUnderProjectTableViewCell.xib where it holds the exact same view as before NNVerticalStackTableViewCell.xib with your added controls. Then subclass it to NNPropertiesUnderProjectTableViewCell.swift with a unique identifer: NNPropertiesUnderProjectTableViewCell.

in which NNPropertiesUnderProjectTableViewCell is a subclas of NNVerticalStackTableViewCell.

From here, just add your additional controls unique to NNPropertiesUnderProjectTableViewCell class.

like image 22
NFerocious Avatar answered Oct 22 '22 03:10

NFerocious


You can Do like this if you want to use tableViewCell.xib in multiple Time. First Go to File and Create New File (Cocoa Touch Class).

CocoaTouch Class

Create TableViewCell File With .xib

TableViewCell

Now Simple Create your Custom Cell Design

Design

Now Add this code in your File TableViewCell.swift

Image

Now just add identifier in your tableView Cell like this (where you want to add this custom TableviewCell)

cell

Now just take it as your Cell Like this..

Table

And Bingo You got it..

Now just add cell as! TableViewCell in any TableViewController File (You got same results with same Design.)

OutPut1

Here of Click First (Load First TableViewController)

FirstTable

On Click Second (Load Second TableViewController)

SecondTable View

like image 2
Dhruv Khatri Avatar answered Oct 22 '22 03:10

Dhruv Khatri


Basically, you can't do exactly what you're trying to do because the class name is in the XIB so you always get an instance of the base class, not any of your subclasses.

The suggestion from @Tj3n is a good one, extract the common part into a reusable view and in your superclass initialisation create an instance of that view and add it. Now, when you instantiate a subclass and it calls super the common element will be initialised and usable by the subclass.

In other words, use composition to achieve your goal, not inheritance.

like image 1
Wain Avatar answered Oct 22 '22 03:10

Wain