一、创建项目
创建一个项目,名为 TableTwo,预实现效果如下:
TableView里面嵌套TableView,里面的TableView可以展开、隐藏,可以侧滑删除
二、storyboard 布局二级 TableView
1、基础布局
2、外层TableView dataSource、datagate:直接关联View Controler
3、内层TableView dataSource、datagate:关联外层Table View Cell
三、代码相关
1、代码图示、TableView关联:外层-TitleCell、内层-ContentCell
DataModel:数据模型
TitleCell:标题模块
ContentCell:内容模块
MyInterface:数据传递接口
2、DataModel:数据模型
struct DataModel: Encodable{
//标题
var title : String!
//内容列表
var content : [String]!
//显示、隐藏
var isHide : Bool!
}
3、TitleCell:标题模块
import UIKit
class TitleCell: UITableViewCell, UITableViewDataSource, UITableViewDelegate {
//标题
@IBOutlet weak var tvTitle: UILabel!
//内容数量
@IBOutlet weak var tvContentNumber: UILabel!
//内部内容 TableView
@IBOutlet weak var contentTable: UITableView!
//声明数据传输接口
var sendContent:SendContent?
var listData:Array = [String]()
//内层数据数
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listData.count
}
//内部Cell
var contentCell:ContentCell?
//设置内层数据
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
contentCell = (tableView.dequeueReusableCell(withIdentifier: "ContentCell", for: indexPath) as! ContentCell)
let row = (indexPath as NSIndexPath).row
//设置序号
contentCell?.tvSerialNumber.text = "\(row + 1)"
//设置内容
contentCell?.tvContent.text = listData[row]
return contentCell!
}
//点击事件
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//let row = (indexPath as NSIndexPath).row
//sendContent!(listData[row], row)
}
//设置为删除模式
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return .delete
}
//侧滑删除
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
let row = (indexPath as NSIndexPath).row
sendContent!(listData[row], row)
//self.listData.remove(at: (indexPath as NSIndexPath).row)
//self.codeTable.deleteRows(at: [indexPath], with: .fade)
//self.codeTable.reloadData()
}
func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
return "删除"
}
//设置每条内容的高度
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 40
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
contentTable.reloadData()
// Configure the view for the selected state
}
}
4、ContentCell:内容模块
class ContentCell: UITableViewCell {
//内容序号
@IBOutlet weak var tvSerialNumber: UILabel!
//内容
@IBOutlet weak var tvContent: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
5、MyInterface:数据传递接口
typealias SendContent = (_ content:String,_ postion:Int) -> Void
6、ViewController
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
//标题输入框
@IBOutlet weak var etTitle: UITextField!
//内容输入框
@IBOutlet weak var etContent: UITextField!
//确定添加标题、内容
@IBAction func btnAddData(_ sender: Any) {
if self.etTitle.text == ""{
self.alertsOne(contents: "请先输入标题")
return
}
if self.etContent.text == ""{
self.alertsOne(contents: "请先输入内容")
return
}
var isExistence = false
for i in 0..<self.listData.count{
if self.listData[i].title == self.etTitle.text{
//如果已经有这个标题了,就往这个标题下直接添加内容
isExistence = true
self.listData[i].content.append(self.etContent.text!)
}
}
if !isExistence{
//如果还没有这个标题,就添加标题、内容
self.listData.append(DataModel.init(title: self.etTitle.text!, content: [self.etContent.text!], isHide: false))
}
self.tableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
//外部 TableView
@IBOutlet weak var tableView: UITableView!
var listData:Array = [DataModel]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listData.count
}
var titleCell:TitleCell?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
titleCell = (tableView.dequeueReusableCell(withIdentifier: "TitleCell", for: indexPath) as! TitleCell)
let row = (indexPath as NSIndexPath).row
titleCell?.tvTitle.text = listData[row].title ?? ""
titleCell?.tvContentNumber.text = "\(listData[row].content.count)"
titleCell?.listData = listData[row].content
titleCell?.sendContent = {(content : String, postion : Int) -> Void in
//内部的侧滑删除:删除内容
self.listData[row].content.remove(at:self.listData[row].content.firstIndex(of: content) ?? 0)
//如果一条内容都没有,就删除标题
if self.listData[row].content.count == 0{
self.listData.remove(at: row)
}
//刷新数据
self.tableView.reloadData()
}
return titleCell!
}
//点击事件-点击展开或隐藏
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let row = (indexPath as NSIndexPath).row
if listData[row].isHide{
listData[row].isHide = false
}else{
listData[row].isHide = true
}
self.tableView.reloadData()
}
//设置为删除模式-当前设置为不能侧滑删除
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return .none
}
//侧滑删除
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
self.listData.remove(at: (indexPath as NSIndexPath).row)
self.tableView.deleteRows(at: [indexPath], with: .fade)
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let row = (indexPath as NSIndexPath).row
if listData[row].isHide{
return CGFloat(70 + listData[row].content.count*40)
}else{
return 50
}
}
//MARK: - 单按钮提示框
func alertsOne(contents:String){
let alert:UIAlertController = UIAlertController(title: "温馨提示", message: contents, preferredStyle: UIAlertController.Style.alert)
let yesAction = UIAlertAction(title: "确定", style: .cancel) { (UIAlertAction) in
}
alert.addAction(yesAction)
//以模态方式弹出
self.present(alert, animated: true, completion: nil)
}
}