Swift 通过 storyboard 实现 TableView 二级嵌套

15 篇文章 1 订阅
11 篇文章 1 订阅

GitHub - iscopy/TableTwo: iOS swift TableView 二级嵌套、折叠iOS swift TableView 二级嵌套、折叠. Contribute to iscopy/TableTwo development by creating an account on GitHub.https://github.com/iscopy/TableTwo

一、创建项目

        创建一个项目,名为 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)
    }
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值