swift 4.2 TableView列表操作

燕玉堂
2023-12-01

对于开发应用来说,列表是最常用到一个控件,而且对于列表的操作也最多,我们比较常用的有插入、删除、多选、排序、索引等等。那么今天我们就一一的实现我们这些功能。我们下面要用到Version 10.1,swift 版本是4.2,在这个环境下实现。如果有不同的版本,有可能不兼容,毕竟swift版本现在还没有稳定。

以手机通讯录为例,我们先来梳理一下思路:

  • 插入操作:当我们要插入一个人的信息时候,我们需要判断插入的的人的姓名的首字母属于在第二个section里,我们先找到要这个secion,然后,我们在把这条数据直接做插入操作。如果当前没有改字母列表,我们就要添加一个新的secion来显示我们的数据,这时候就要插入一个secion,而不是一row了。
  • 删除操作:删除一行很简单,直接调用删除列表就行,但是,如我们不注意,就会出错。当删除这条数据的时候,如果当前的section还有数据,那就没问题,如果当前的secion没有数据了,在插入就崩溃,原因就是我们没有吧数据源的secion和索引删除。只有把这两个数据都删除,才可以。
  • 多选操作: 多选就简单多了,但是要主注意,如果我们使用原生的cell,那么cell.selectionStyle一定不要设置为.none,否则你就看不到你选中的效果了,如果是自定义的,那你可以忽略,但是选中与取消的逻辑需要自己实现。
  • 排序操作:这个是按照字母排序的,应该没有什么难度的。
  • 索引操作:这个是根据选中的字母直接跳到改字母开头的secion中。

说了这么多没有代码感觉都像(废)很(话)深(很)奥(多)一样。那我们就撸撸代码。

class ViewController: JHSBaseViewController {

    var sectionList = [String:[PersonModel]]();
    var sectionKeys = [String]();
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        title = "列表操作";
        
        createTable(delegate: self);
        baseTable.allowsSelectionDuringEditing = true;
        baseTable.allowsMultipleSelectionDuringEditing = true;
        baseTable.allowsMultipleSelection = true;
        baseTable.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        baseTable.separatorStyle = .singleLine;
        
        
        let selectedAll = UIBarButtonItem(title: "全选", style: .done, target: self, action: #selector(buttonItemAction(_:)));
        selectedAll.tag = ViewTagSense.selectedAllTag.rawValue;
        
        let edit = UIBarButtonItem(title: "编辑", style: .plain, target: self, action: #selector(buttonItemAction(_:)));
        edit.tag = ViewTagSense.editTag.rawValue;
        self.navigationItem.rightBarButtonItems = [edit,selectedAll];
        
        resetPersonModel();
        
        let addItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(buttonItemAction(_:)));
        addItem.tag = ViewTagSense.addTag.rawValue;
        navigationItem.leftBarButtonItem = addItem;
        
    }
    
    // 给数据按照字母分组,并排序
    func resetPersonModel() -> Void {
        let modelList = PersonModel.createPersons();

        for item in modelList {
            
            var pList = sectionList[item.firstPY] ?? [PersonModel]();
            pList.append(item);
            sectionList[item.firstPY] = pList;
            if !sectionKeys.contains(item.firstPY) {
                sectionKeys.append(item.firstPY);
            }
        }
        sectionKeys.sort { (first, second) -> Bool in
            return first.compare(second) == ComparisonResult.orderedAscending;
        }
    }
    
    @objc override func buttonItemAction(_ item: UIBarButtonItem) {
       
        if item.tag == ViewTagSense.editTag.rawValue {
            item.title = !baseTable.isEditing ? "完成" : "编辑";
            baseTable.setEditing(!baseTable.isEditing, animated: true);
            baseTable.reloadData();
            
        }else if item.tag == ViewTagSense.selectedAllTag.rawValue {
            if !baseTable.isEditing {
                return;
            }
            for key in sectionKeys.enumerated() {
                guard let list = sectionList[key.element] else{
                    continue;
                }
                for item in list.enumerated() {
                    baseTable.selectRow(at: IndexPath.init(item: item.offset, section: key.offset), animated: true, scrollPosition: .none);
                }
            }
        }else if item.tag == ViewTagSense.addTag.rawValue {
            let ctrl = AddPersonViewController();
            ctrl.finishedDone = {
                (model: PersonModel) -> Void in
                self.addModelTo(model: model);
            }
            present(ctrl, animated: true) {
                
            };
        }
        
    }
    
    func deleteModelBy(indexPath: IndexPath) -> Void {
        let key = sectionKeys[indexPath.section];
        guard var list = sectionList[key] else {
            return;
        }
        list.remove(at: indexPath.row);
        if list.count == 0 {
            sectionList.removeValue(forKey: key);
            sectionKeys.remove(at: indexPath.section);
            baseTable.deleteSection(section: indexPath.section);
        }else {
            sectionList[key] = list;
            baseTable.deleteRows(indexPaths: [indexPath]);
        }
        
    }
    
    func addModelTo(model: PersonModel) -> Void {
        let key = model.firstPY;
        if let idx = sectionKeys.firstIndex(of: key) {
            var list = sectionList[key] ?? [PersonModel]();
            list.insert(model, at: 0);
            sectionList[key] = list;
            if list.count == 1 {
                baseTable.insertSection(section: idx);
            }else {
                baseTable.insertRows(indexPaths: [IndexPath.init(row: 0, section: idx)]);
            }
            
        }else {
            sectionKeys.append(key);
            sectionKeys.sort { (first, second) -> Bool in
                return first.compare(second) == ComparisonResult.orderedAscending;
            }
            addModelTo(model: model);
        }
    }
    
    //
    


}
// MARK: - Table View operation
extension ViewController {
    // MAEK: - table view delegate implement
    
    override func numberOfSections(in tableView: UITableView) -> Int {
        return sectionList.count;
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let count = sectionList[sectionKeys[section]]?.count ?? 0;
        return count;
    }
    func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        return true;
    }
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sectionKeys[section];
    }
    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
        let delAction = UITableViewRowAction(style: .default, title: "删除") { (action, deleIndex) in
            self.deleteModelBy(indexPath: indexPath);
        };
        return [delAction];
    }
    
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath);
        let list = sectionList[sectionKeys[indexPath.section]];
        let model = list![indexPath.row];
        cell.textLabel?.text = model.name;
        cell.selectionStyle = tableView.isEditing ? .blue : .none;
        cell.selectionStyle = .none;
        return cell;
        
    }
    
    func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        
    }
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
    }
    
    func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
        return index;
    }
    func sectionIndexTitles(for tableView: UITableView) -> [String]? {
        return sectionKeys;
    }
}

 首先我们定义了一个字典,这个字典的键就是我们每组人的首个字母,值就是当前组人的列表。第二个数组是有多少组。

func resetPersonModel()这个函数是给所有的人员按照字母分组,并排序。func deleteModelBy(indexPath: IndexPath)这个是删除一条数据,我们需要判断删除完这条数据还没有剩下的。有就删row,没有就删secion。func addModelTo(model: PersonModel)这个使我们添加数据的。这个也要判断是否现在的列表已经有了改数据的secion,有就直接在改secion加row,没有就要添加一个secion。我们用了一个递归函数。baseTable.selectRow(at: IndexPath.init(item: item.offset, section: key.offset), animated: true, scrollPosition: .none) 这个就是选中一个具体数据。

下面是PersonModel数据模型:

class PersonModel: BaseModel {
    var name = "";
    var isSelected = false;
    private var namePY: String!
    var firstPY: String {
        if namePY == nil {
            namePY = name.firstPinYin;
        }
        return namePY;
    }
    class func createPersons() -> [PersonModel] {
        let path = Bundle.main.path(forResource: "PersonList", ofType: "plist");
        let dict = NSDictionary(contentsOfFile: path!)!;
        var list = [PersonModel]();
        for idx in dict {
            let p = PersonModel();
            p.name = idx.key as? String ?? "未命名";
            list.append(p);
        }
        return list;
    }
}

 

最后的最后,没有demo也不算完美,demo链接欢迎指正。 

 类似资料: