简体   繁体   中英

Dismiss UIViewController for TableViewCell

I have a tableview inside of an UIViewController. This tableview has a dynamic table with buttons.

I set the function for each button inside of the TableViewCell like this:

class ButtonTableViewCell: UITableViewCell {

    let defaults = UserDefaults.standard
    var targetTitle: String!

    @IBOutlet weak var buttonDisplay: UIButton!

    func setButton(title: String) {
        buttonDisplay.setTitle(title.uppercased(), for: .normal)
        targetTitle = title
        buttonDisplay.addTarget(self, action: #selector(changeValue(_:)), for: .touchUpInside)
    }

    @objc func changeValue(_ sender: Any) {
        currentCar = targetTitle
        defaults.set(currentCar, forKey: "currentCar")
    }

}

How can I dismiss the UIViewController which contains the TableView within the function @objc func changeValue(_ sender: Any) ?

Furthermore, since the buttons are being added dynamically, I do also need a dynamic height for the tableview itself - how can I adjust tableview's with every added cell?

UIViewController:

class DropdownViewController: UIViewController {

    @IBOutlet weak var tableViewButtons: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        tableViewButtons.delegate = self
        tableViewButtons.dataSource = self
    }

}

extension DropdownViewController: UITableViewDataSource, UITableViewDelegate {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return carsArray.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let rowData = carsArray[indexPath.row]

        let cell = tableView.dequeueReusableCell(withIdentifier: "buttonCell") as! ButtonTableViewCell
        cell.setButton(title: rowData.name)
        return cell
    }
}

You can use delegates:

protocol ButtonTableViewCellDelegate {
   func dismissFromCell()
}

class ButtonTableViewCell: UITableViewCell {

    let defaults = UserDefaults.standard
    var targetTitle: String!

    // Delegate should be weak to avoid memory leaks
    weak var delegate: ButtonTableViewCellDelegate?

    @IBOutlet weak var buttonDisplay: UIButton!

    func setButton(title: String) {
        buttonDisplay.setTitle(title.uppercased(), for: .normal)
        targetTitle = title
        buttonDisplay.addTarget(self, action: #selector(changeValue(_:)), for: .touchUpInside)
    }

    @objc func changeValue(_ sender: Any) {
        currentCar = targetTitle
        defaults.set(currentCar, forKey: "currentCar")
        delegate?.dismissFromCell()
    }
}

class DropdownViewController: UIViewController {

    @IBOutlet weak var tableViewButtons: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        tableViewButtons.delegate = self
        tableViewButtons.dataSource = self
    }

}

extension DropdownViewController: UITableViewDataSource, UITableViewDelegate {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return carsArray.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let rowData = carsArray[indexPath.row]

        let cell = tableView.dequeueReusableCell(withIdentifier: "buttonCell") as! ButtonTableViewCell
        cell.setButton(title: rowData.name)
        // Setting Delegate here
        cell.delegate = self
        return cell
    }
}

// Extend your controller to conform your Delegate Protocol
extension DropdownViewController: ButtonTableViewCellDelegate {
   func dismissFromCell() {
       self.dismiss()
   }
}

You can get more info about delegation pattern here: https://www.appcoda.com/swift-delegate/

You'll want to use a delegate to perform the action. Just create a protocol with a function, and call the delegate within your changeValue function.

Otherwise, use this:

var responder: UIResponder! = self
repeat { responder = responder.next } while !(responder is UIViewController)
(responder as! UIViewController).dismiss()

It just goes up the responder chain until it finds a UIViewController, and then performs any action needed. Only use this if you have a UIViewController as a parent somewhere, otherwise it won't work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM