对于开发应用来说,列表是最常用到一个控件,而且对于列表的操作也最多,我们比较常用的有插入、删除、多选、排序、索引等等。那么今天我们就一一的实现我们这些功能。我们下面要用到Version 10.1,swift 版本是4.2,在这个环境下实现。如果有不同的版本,有可能不兼容,毕竟swift版本现在还没有稳定。
以手机通讯录为例,我们先来梳理一下思路:
说了这么多没有代码感觉都像(废)很(话)深(很)奥(多)一样。那我们就撸撸代码。
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链接欢迎指正。