Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I reuse a table view in multiple view controllers in Swift?

I'm working on an app right now that requires the exact same table view in multiple scenes on my app, however, the data and the placement of the table will change, as illustrated in these two pictures (table view highlighted in red)

enter image description here

enter image description here

In all instances of the table throughout the app, it should have:

  1. The same delegate methods
  2. The same datasource methods (all though the actual data will change)
  3. The same table view cell types with the same outlets and actions.
  4. The same internal constraints (I don't want to have to manually add constraints for the table cells each and every time).

Right now I'm coding them as two separate table views in two separate view controllers, however, I've realized I will need to replicate the same table and logic in many more places throughout my app and this doesn't feel like the right way to go about. So my question is, how can you accomplish table replication in iOS (using interface builder or swift) that meets the specs above, in a clean and dry way?

like image 717
Josh Hadik Avatar asked Oct 23 '17 21:10

Josh Hadik


1 Answers

If you want to design your cells once and then use them across different table views in different view controllers you have to design them in the separate .xib files. Prototype cells are per view controller and don't scale very well.

If all the data source and delegate methods are the same, you can move implementation of this protocols to the separate class. You can configure this class with the array of items to display.

class ReusableTableView: NSObject, UITableViewDataSource, UITableViewDelegate
{
    var tableView: UITableView
    var tableViewData: [String]

    init(_ tv: UITableView, _ data: [String])
    {
        tableViewData = data
        tableView = tv
        super.init()
        tableView.delegate = self
        tableView.dataSource = self

        // Register all of your cells
        tableView.register(UINib(nibName: "SomeNib", bundle: nil), forCellReuseIdentifier: "example-id")
    }

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

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return tableView.dequeueReusableCell(withIdentifier: "example-id", for: indexPath)
    }
}

Having this two building blocks you can layout the table view separately on each view controller and wire it up with your reusable data source/delegate.

class ExampleTablewViewController: UIViewController
{
    @IBOutlet weak var tableView: UITableView!
    var reusableTableView: ReusableTableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        reusableTableView = ReusableTableView(tableView, ["lorem", "ipsum", "dolor"])
        reusableTableView.tableView.reloadData()
    }
}

You can find a basic example of how I see this in this GitHub repo.

like image 139
Kamil Szostakowski Avatar answered Oct 14 '22 18:10

Kamil Szostakowski