Delegate Method to UItableViewCell Swift

2019-03-02 14:37发布

问题:

I have a Social Network Feed in form UItableView which has a cell. Now each cell has an image that animates when an even is triggered. Now, This event is in form of a string, will be triggered at every cell. the options for the event are defined in another class(of type NSObject).

My issue: I constructed a protocol delegate method in table view, which will be called whenever the event is triggered for each cell. Then, I define this function in UITableViewCell Class, since my the image will be animating on that. All is working well but I am unable to figure out how to assign the delegate of TableView class to cell class. What I mean is, how can I use UITableView.delegate = self in cellView class. I have tried using a static variable, but it doesn't work.

I have been playing around the protocols for a while now but really unable to figure out a solution to this.

I hope I am clear. If not, I will provide with an example in the comments. I am sorry, This is a confidential project and I cant reveal all details.

回答1:

If I correctly understood your question, maybe this could help:

class ViewController: UIViewController, YourCustomTableDelegate {

@IBOutlet weak var tableView: YourCustomTableView!  

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.customTableDelegate = self
    }


    // table delegate method
    func shouldAnimateCell(at indexPath: IndexPath) {
       if let cell = tableView.cellForRow(at: indexPath) {
           cell.animate(...)
       }    
    }
}


回答2:

Try something like this:

Define your delegate protocol:

protocol CustomCellDelegate: class {
    func animationStarted()
    func animationFinished()
}

Define your CustomCell. Extremely important to define a weak delegate reference, so your classes won't retain each other.

class CustomCell: UITableViewCell {
    // Don't unwrap in case the cell is enqueued!
    weak var delegate: CustomCellDelegate?

    /* Some initialization of the cell */

    func performAnimation() {
        delegate?.animationStarted()
        UIView.animate(withDuration: 0.5, animations: {
            /* Do some cool animation */
        }) { finished in
            self.delegate?.animationFinished()
        }
    }
}

Define your view controller. assign delegate inside tableView:cellForRowAt.

class ViewController: UITableViewDelegate, UITableViewDataSource {

    /* Some view controller customization */

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: CustomCell.self)) as? CustomCell
        cell.delegate = self
        cell.performAnimation()
        return cell
    }
}


回答3:

If I understand you correctly, you are trying to make each of your cells conform to a protocol that belongs to their UITableView? If this is the case then this cannot be done. The Delegation design pattern is a one to one relationship, i.e only one of your UITableViewCells would be able to conform to the UITableView's delegate.

Delegation is a simple and powerful pattern in which one object in a program acts on behalf of, or in coordination with, another object. The delegating object keeps a reference to the other object—the delegate—and at the appropriate time sends a message to it. The message informs the delegate of an event that the delegating object is about to handle or has just handled. The delegate may respond to the message by updating the appearance or state of itself or other objects in the application, and in some cases it can return a value that affects how an impending event is handled. The main value of delegation is that it allows you to easily customize the behavior of several objects in one central object.

Quote from the Apple Docs

I would suggest that your UITableViewCell should call a block (Objective-C) or a closure (Swift) whenever your specified event is triggered to achieve what you are looking for. Set up this closure in your tableView:cellForRowAtIndexPath function.

EXAMPLE

TableViewController

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
  {
    let cell = tableView.dequeueReusableCell(withIdentifier: "MyTableViewCellID", for: indexPath) as! MyTableViewCell
    cell.eventClosure = {
     //Do something once the event has been triggered.
    }
    return cell
  }

TableViewCell

func eventTriggered()
{
  //Call the closure now we have a triggered event.
  eventClosure()
}