Swift - 表格section header增加滑动删除功能(删除该分区下所有cell)
我们知道 UITableView 的单元格自带滑动删除功能,设置后只要在单元格 cell 上向左滑动,右侧就会自动出现删除按钮,如下图:

但这样一次只能删除一条记录,不能批量删除。我们可以通过自定义表格的分组头(section header),在其上面增加滑动删除功能,这样滑动分组头时就可以删除该 section 下所有的单元格。
1,效果图
- 在分区头部(section header)上向左滑动,右侧会出现一个“全部删除”按钮。向右滑动又会隐藏删除按钮。这两个过程都是有动画效果的。
- 点击“全部删除”按钮,可以将其所在的整个分区数据删除。
注意:建议使用真机进行调试,模拟器运行时会出现只有一个分区头可以滑动删除的问题。

2,样例代码
(1)SwipeableSectionHeader.swift(自定义的滑动分区头)
import UIKit
//自定义滑动分区头代理协议
protocol SwipeableSectionHeaderDelegate{
//删除分区
func deleteSection(section: Int)
}
//自定义滑动分区头
class SwipeableSectionHeader: UIView {
//分区索引
var section:Int = 0
//放置文本标签和按钮的容器
var container:UIView!
//标题文本标签
var titleLabel:UILabel!
//删除按钮
var deleteButton:UIButton!
//代理对象
var delegate:SwipeableSectionHeaderDelegate?
//向左滑动手势
var swipeLeft:UISwipeGestureRecognizer!
//向右滑动手势
var swipeRight:UISwipeGestureRecognizer!
override init(frame: CGRect) {
super.init(frame: frame)
//背景为黑色
self.backgroundColor = UIColor.black
//初始化容器
self.container = UIView()
self.addSubview(container)
//初始标题文本标签
self.titleLabel = UILabel()
self.titleLabel.textColor = UIColor.white
self.titleLabel.textAlignment = .center
self.container.addSubview(self.titleLabel)
//初始化删除按钮
self.deleteButton = UIButton(type: .custom)
self.deleteButton.backgroundColor = UIColor(red: 0xfc/255, green: 0x21/255,
blue: 0x25/255, alpha: 1)
self.deleteButton.setTitle("删除全部", for:.normal)
self.deleteButton.titleLabel?.font = UIFont.systemFont(ofSize: 15)
self.deleteButton.addTarget(self, action:#selector(buttonTapped(_:)), for:.touchUpInside)
self.container.addSubview(self.deleteButton)
//向左滑动手势
self.swipeLeft = UISwipeGestureRecognizer(target:self,
action:#selector(headerViewSwiped(_:)))
self.swipeLeft.direction = .left
self.addGestureRecognizer(self.swipeLeft)
//向右滑动手势
self.swipeRight = UISwipeGestureRecognizer(target:self,
action:#selector(headerViewSwiped(_:)))
self.swipeRight.direction = .right
self.addGestureRecognizer(self.swipeRight)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//滑动响应
@objc func headerViewSwiped(_ recognizer:UISwipeGestureRecognizer){
if recognizer.state == .ended {
var newFrame = self.container.frame
//向左滑动显示出删除按钮,向右滑动隐藏删除按钮
if recognizer.direction == .left {
newFrame.origin.x = -self.deleteButton.frame.width
}else{
newFrame.origin.x = 0
}
//播放动画
UIView.animate(withDuration: 0.25, animations: {
()-> Void in
self.container.frame = newFrame
})
}
}
//删除按钮点击
@objc func buttonTapped(_ button:UIButton){
delegate?.deleteSection(section: section)
}
//子视图布局
override func layoutSubviews() {
super.layoutSubviews()
self.container.frame = CGRect(x: 0, y:0, width:self.frame.width + 74,
height:self.frame.height)
self.titleLabel.frame = CGRect(x: 0, y:0, width:self.frame.width,
height:self.frame.height)
self.deleteButton.frame = CGRect(x: self.frame.size.width, y:0, width:74,
height:self.frame.height)
}
}
(2)ViewController.swift(使用样例)
import UIKit
class ViewController: UIViewController, UITableViewDelegate,
UITableViewDataSource,UIGestureRecognizerDelegate,
SwipeableSectionHeaderDelegate{
var tableView:UITableView!
var adHeaders:[String]!
var allnames:[[String]]!
override func loadView() {
super.loadView()
}
override func viewDidLoad() {
super.viewDidLoad()
//初始化数据,这一次数据,我们放在属性列表文件里
self.allnames = [["UILabel 标签","UIButton 按钮"],
["UIDatePiker 日期选择器","UITableView 表格视图"],
["UICollectionView 网格"]
]
self.adHeaders = [
"常见 UIKit 控件",
"中级 UIKit 控件",
"高级 UIKit 控件"
]
//创建表视图
self.tableView = UITableView(frame:self.view.frame, style:.grouped)
self.tableView.delegate = self
self.tableView.dataSource = self
//创建一个重用的单元格
self.tableView.register(UITableViewCell.self,
forCellReuseIdentifier: "SwiftCell")
self.view.addSubview(self.tableView)
}
//在本例中,有3个分区
func numberOfSections(in tableView: UITableView) -> Int {
return self.adHeaders.count
}
//返回表格行数(也就是返回控件数)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let data = self.allnames[section]
return data.count
}
//返回自定义的分区头
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = SwipeableSectionHeader()
//设置代理
headerView.delegate = self
//设置标题
headerView.titleLabel.text = self.adHeaders[section]
//设置分区索引
headerView.section = section
//设置手势优先级(否则将与表格自带的手势冲突,造成滑动分区头时出现第一个cell的删除按钮)
if let gestureRecognizers = tableView.gestureRecognizers {
for recognizer in gestureRecognizers {
recognizer.require(toFail: headerView.swipeLeft)
}
}
return headerView
}
//返回分区头部高度
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int)
-> CGFloat {
return 40
}
// UITableViewDataSource协议中的方法,该方法的返回值决定指定分区的尾部
func tableView(_ tableView: UITableView, titleForFooterInSection section: Int)
-> String? {
let data = self.allnames[section]
return "有\(data.count)个控件"
}
//创建各单元显示内容(创建参数indexPath指定的单元)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
-> UITableViewCell {
//为了提供表格显示性能,已创建完成的单元需重复使用
let identify:String = "SwiftCell"
//同一形式的单元格重复使用,在声明时已注册
let cell = tableView.dequeueReusableCell(withIdentifier: identify,
for: indexPath)
cell.accessoryType = .disclosureIndicator
let secno = indexPath.section
var data = self.allnames[secno]
cell.textLabel?.text = data[indexPath.row]
return cell
}
//删除整个分区
func deleteSection(section: Int) {
self.adHeaders.remove(at: section)
self.allnames.remove(at: section)
self.tableView.reloadData()
}
//设置单元格的编辑的样式
func tableView(_ tableView: UITableView,
editingStyleForRowAt indexPath: IndexPath)
-> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.delete
}
//设置确认删除按钮的文字
func tableView(_ tableView: UITableView,
titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
return "删除"
}
//单元格编辑后(删除或插入)的响应方法
func tableView(_ tableView: UITableView,
commit editingStyle: UITableViewCellEditingStyle,
forRowAt indexPath: IndexPath) {
self.allnames[indexPath.section].remove(at: indexPath.row)
self.tableView.reloadData()
print("你确认了删除按钮")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}

你这个 会存在复用问题吧
真机调试也是一样的情况,代码对比过好几次了都是跟你一样的,不知道问题出在哪
为什么第一个分区头可以左滑,其他的分区头都不行