Search code examples
swiftgenericsdelegatesdelegationredundancy

removing the duplicating code code from cell delegate


I have a tableview, to configure a cell (from VC),

cell.model = dataSource[indexpath.row]

In the didSet of cell.model, I am initialising the cell contents. Cell has 3 buttons, tapping on which, I am informing the VC through CellDelegate

protocol CellDelegate {
    func didTapButton1(model: Model)
    func didTapButton2(model: Model)
    func didTapButton3(model: Model)
}

My concern:- I don't want to pass the model here (as it is already associated with the Cell - somehow need to fetch the model from cell) I would like to call didTapButton() without the parameter. Then in the VC,

extension VC: CellDelegate {
//I need to fetch the model associated with the cell.
    func didTapButton1() { }
    func didTapButton2() { }
    func didTapButton3() { }
}

I could achieve this using closure, but it is not preferred here. Any help would be appreciated.*


Solution

  • I'm guessing the reason why you don't want to pass the model is because having a model in all three methods look like code duplication. Well, if you have look at the delegates in the framework, such as UITableViewDelegate, UITextFieldDelegate, most, if not all, of them accept the thing that they are a delegate of as the first parameter. All the methods in UITableViewDelegate has a tableView parameter. Therefore, it would be OK for you to follow the pattern as well:

    protocol CellDelegate {
        func didTapButton1(_ cell: Cell)
        func didTapButton2(_ cell: Cell)
        func didTapButton3(_ cell: Cell)
    }
    

    Personally, I would write only one method in this delegate:

    protocol CellDelegate {
        func didTapButton(_ cell: Cell, buttonNumber: Int)
    }
    

    In the VC extension, you simply check buttonNumber to see which button is pressed:

    switch buttonNumber {
        case 1: button1Tapped()
        case 2: button2Tapped()
        case 3: button3Tapped()
        default: fatalError()
    }
    
    // ...
    
    func button1Tapped() { ... }
    func button2Tapped() { ... }
    func button3Tapped() { ... }