in my project I have a UITableView
. The cells
inside of that contains among other things a UIButton
which acts like a "check-box", so the user can tick of a task.
My question: How can I delete a cell
after the user presses the UIButton
inside of it?
This is my customCell
:
import UIKit
class WhishCell: UITableViewCell {
let label: UILabel = {
let v = UILabel()
v.font = UIFont(name: "AvenirNext", size: 23)
v.textColor = .white
v.font = v.font.withSize(23)
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
let checkButton: UIButton = {
let v = UIButton()
v.backgroundColor = .darkGray
// v.layer.borderColor = UIColor.red.cgColor
// v.layer.borderWidth = 2.0
v.translatesAutoresizingMaskIntoConstraints = false
v.setBackgroundImage(UIImage(named: "boxUnchecked"), for: .normal)
return v
}()
public static let reuseID = "WhishCell"
required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.backgroundColor = .clear
// add checkButton
self.contentView.addSubview(checkButton)
self.checkButton.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 20).isActive = true
self.checkButton.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
self.checkButton.widthAnchor.constraint(equalToConstant: 40).isActive = true
self.checkButton.heightAnchor.constraint(equalToConstant: 40).isActive = true
self.checkButton.addTarget(self, action: #selector(checkButtonTapped), for: .touchUpInside)
// add label
self.contentView.addSubview(label)
self.label.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 70).isActive = true
self.label.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
}
@objc func checkButtonTapped(){
self.checkButton.setBackgroundImage(UIImage(named: "boxChecked"), for: .normal)
self.checkButton.alpha = 0
self.checkButton.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
UIView.animate(withDuration: 0.3) {
self.checkButton.alpha = 1
self.checkButton.transform = CGAffineTransform.identity
}
}
}
When you are creating the cell and setting the button selector all you need to set button tag and selector like this:
self.checkButton.tag = indexPath.row
self.checkButton.addTarget(self, action: #selector(checkButtonTapped(sender:)), for: .touchUpInside)
and make change this in selector:
@objc func checkButtonTapped(sender : UIButton){
let index = sender.tag
self.tableView.deleteRows(at: [index], with: .automatic)
//Add all your code here..
}
Thanks
You can access the tableView
and the indexPath
within the cell with this extension:
extension UITableViewCell {
var tableView: UITableView? {
return (next as? UITableView) ?? (parentViewController as? UITableViewController)?.tableView
}
var indexPath: IndexPath? {
return tableView?.indexPath(for: self)
}
}
With the help of this other extension:
extension UIView {
var parentViewController: UIViewController? {
var parentResponder: UIResponder? = self
while parentResponder != nil {
parentResponder = parentResponder!.next
if let viewController = parentResponder as? UIViewController {
return viewController
}
}
return nil
}
}
So then you can delete the cell as usual:
tableView!.deleteRows(at: [indexPath!], with: .automatic)
Note that the tableView should be responsible for managing cells.
A swifty way is a callback closure.
In the cell add a property
var callback : ((UITableViewCell) -> Void)?
In the action call the callback and pass the cell
@objc func checkButtonTapped(){
...
callback?(self)
}
In the controller in cellForRowAt
assign a closure to the callback property
cell.callback = { cell in
let indexPath = tableView.indexPath(for: cell)!
// insert here a line to remove the item from the data source array.
tableView.deleteRows(at: [indexPath], with: .automatic)
}
This native Swift solution is much more efficient than assigning tags, objective-c-ish target/action or cumbersome view hierarchy math .
Change your checkButtonTapped whit this
@objc func checkButtonTapped() {
self.checkButton.setBackgroundImage(UIImage(named: "boxChecked"), for: .normal)
self.checkButton.alpha = 0
self.checkButton.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
UIView.animate(withDuration: 0.3) {
self.checkButton.alpha = 1
self.checkButton.transform = CGAffineTransform.identity
}
if let tableView = self.superview as? UITableView {
let indexPath = tableView.indexPath(for: self)
tableView.dataSource?.tableView!(tableView, commit: .delete, forRowAt: indexPath!)
}
}
And add the next method to your UITableViewDelegate implementation
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
print("Deleted")
self.texts.remove(at: indexPath.row)
self.tableview.deleteRows(at: [indexPath], with: .automatic)
}
}
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.