crost
crost

Reputation: 192

How do I use extensions to extend an object's tableview's functionality from the calling class?

Overview
I'm trying to better understand how extensions work.
In my app I have a ViewController. There I put a view of another class. In this custom class I put a bunch of buttons and a table view. I want them to display some text inside of my tableView whenever I press them.
The problem is that I want to edit some of the table view functions in order to better adjust it to my ViewController.

What I know
All I know is based on the apple documentation

What I'm doing
What I'm trying to do, I should say, is to add functionality to a custom view's function after adding an object which is of the type of my custom class to the ViewController.

This is my custom class:

class CustomClass: UIView{
@IBOutlet weak var abtn: UIButton!
@IBOutlet weak var table: UITableView!

 func setupTable(){ 
 table.delegate = self
        table.dataSource = self
        
        table.register(UITableViewCell.self, forCellReuseIdentifier: "cellId")
        table.backgroundColor = UIColor.black.withAlphaComponent(0.1)
}
}
extension CustomClass: UITableViewDelegate, UITableViewDataSource{
 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
         let cell = table.dequeueReusableCell(withIdentifier: "cellId", for: indexPath)
        
        return cell
    }
 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
      print("I want to add stuff here too")
        
    }
    //And more stuff that is not useful rn
}

Inside of the ViewController class I have declared a variable of type CustomClass.

@IBOutlet weak var custom: CustomClass!
In my viewDidLoad I call :
custom.setupTable()

What I need to do is creating an extension to edit the tableview that belongs to custom (the variable of type CustomClass that is inside of my ViewController).

I have no clue on how to do that.

I know how to work with extension to expand my code's functionality but I don't know how to use them to edit these other functions.

Question
How do I edit the tableview functions that belong to custom?
Ie. how would I be able to change the number of rows or to change the cell's layout from the class I call the object in?

I hope I was clear enough...

Upvotes: 0

Views: 1574

Answers (1)

DonMag
DonMag

Reputation: 77682

For this specific example...

Add a property to your CustomClass:

class CustomClass: UIView {
    
    // this may be changed by the "calling class"
    var numRows: Int = 10
    
    @IBOutlet weak var abtn: UIButton!
    @IBOutlet weak var table: UITableView!
    
    func setupTable(){
        table.delegate = self
        table.dataSource = self
        
        table.register(UITableViewCell.self, forCellReuseIdentifier: "cellId")
        table.backgroundColor = UIColor.black.withAlphaComponent(0.1)
    }
}

In your extension, use that property:

extension CustomClass: UITableViewDelegate, UITableViewDataSource{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // don't make this a hard-coded number
        //return 10
        return numRows
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = table.dequeueReusableCell(withIdentifier: "cellId", for: indexPath)
        
        return cell
    }
    //And more stuff that is not useful rn
}

Then, in your "calling class", you can change that property:

class ExampleViewController: UIViewController {
    
    let myView = CustomClass()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        view.addSubview(myView)
        // constraints, etc
        
        // change the number of rows in the table in myView
        myView.numRows = 20
    }
    
}

More likely, though, you would be doing something like setting / changing the data for the table in your custom class.

Here's an example, along with showing how to use a closure to "call back" to the calling class / controller:

class CustomClass: UIView {
    
    // this may be changed by the "calling class"
    var theData: [String] = []
    
    // closure to "call back" to the controller
    var callback: ((IndexPath) -> ())?
    
    @IBOutlet weak var abtn: UIButton!
    @IBOutlet weak var table: UITableView!
    
    func setupTable(){
        table.delegate = self
        table.dataSource = self
        
        table.register(UITableViewCell.self, forCellReuseIdentifier: "cellId")
        table.backgroundColor = UIColor.black.withAlphaComponent(0.1)
    }
}
extension CustomClass: UITableViewDelegate, UITableViewDataSource{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return theData.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = table.dequeueReusableCell(withIdentifier: "cellId", for: indexPath)
        cell.textLabel?.text = theData[indexPath.row]
        return cell
    }
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // tell the controller the cell was selected
        callback?(indexPath)
    }
}

class ExampleViewController: UIViewController {
    
    let myView = CustomClass()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        view.addSubview(myView)
        // constraints, etc
        
        // set the data in CustomClass
        myView.theData = [
            "First row",
            "Second row",
            "Third",
            "Fourth",
            "etc..."
        ]
        
        myView.callback = { indexPath in
            print("CustomClass myView told me \(indexPath) was selected!")
            // do what you want
        }
    }
    
}

Upvotes: 1

Related Questions