在这一章中学习主要学习到了表视图的应用,普通表视图,表视图的Cell自定义,添加搜索栏,表视图添加索引、分组,静态表视图,删除、插入Cell,移动Cell,下拉刷新,以下为本章Demo代码:
普通表视图 - 下拉刷新基础 - 搜索基础
import UIKit //-------------普通表视图 - 下拉刷新基础 - 搜索基础 class TableViewController: UITableViewController,UISearchBarDelegate { //自定义单元时需要,在storyboard中指定cell的类与标识 var SearchData: NSArray! //搜索结果数据 var TeamData: NSArray! //所有数据 var tempArray: NSArray! //临时数据 @IBOutlet weak var searchBar: UISearchBar! override func viewDidLoad() { super.viewDidLoad() //获取plist文件路径 let plistPath = Bundle.main.path(forResource: "team", ofType: "plist") //获取属性列表文件中的全部数据保存到pickerAllData中 self.TeamData = NSArray(contentsOfFile: plistPath!) //初始化搜索 self.contentForSearchText(searchText: "", scope: -1) //下拉刷新控件初始化 let rc = UIRefreshControl() //定义控件的初始标题 rc.attributedTitle = NSAttributedString(string: "下拉刷新") //下拉事件监听(事件处理),事年与处理方法关联起来(所有控件都有该方法) //@param1:事件在哪个对像里面,@param2:对应的处理方法,@param3:定义事件类型 rc.addTarget(self, action: #selector(TableViewController.refreshTableView), for: UIControlEvents.valueChanged) //将 rc 赋给当前tableView的refreshControl属性 self.refreshControl = rc } func refreshTableView() { //如果正在刷新 if self.refreshControl?.isRefreshing == true { //改控件的标题 为 加载中... self.refreshControl?.attributedTitle = NSAttributedString(string: "加载中...") //TODO 到网络中加载数据 //===================TODO 数据加载成功后 let time: TimeInterval = 3.0//延迟加载时间(单位:秒) DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + time) { //数据加载成功后,停止下拉刷新 self.refreshControl?.endRefreshing() //改控件的标题 改回 下拉刷新 self.refreshControl?.attributedTitle = NSAttributedString(string: "下拉刷新") //重新加载表视图数据 self.tableView.reloadData() } } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } / 过滤结果的方法 @ searchText: 关键字, @ scope: 辅助搜索栏的Tag / func contentForSearchText(searchText: NSString, scope: Int){ if searchText.length == 0 {//如果没有输入搜索内容 self.SearchData = NSMutableArray(array: self.TeamData) //返回所有数据 return } if scope == 0 { //如果英文 //搜索的逻辑条件对像 let scopePredicate = NSPredicate(format: "name contains[cd] %@", searchText) //集合对像都有这个方法,返回的是过滤后的集合 self.tempArray = self.TeamData.filtered(using: scopePredicate) as NSArray! }else if scope == 1 { //如果中文 //搜索的逻辑条件对像 let scopePredicate = NSPredicate(format: "image contains[cd] %@", searchText) //集合对像都有这个方法,返回的是过滤后的集合 self.tempArray = self.TeamData.filtered(using: scopePredicate) as NSArray! } self.SearchData = NSMutableArray(array: self.tempArray) } //searchBarDelegate 协议方法实现 //获得焦点开始输入时 func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool { self.searchBar.showsScopeBar = true //显示辅助搜索栏 self.searchBar.sizeToFit() //加载适合的searchBar的大小 return true } //当用户输入搜索内容时 func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { //调用过滤方法,self.searchBar.selectedScopeButtonIndex 为辅助搜索栏的Tag self.contentForSearchText(searchText: searchText as NSString, scope: self.searchBar.selectedScopeButtonIndex) self.tableView.reloadData()//重新加载表视图数据 } //当用户点击右侧cancel(取消搜索)按钮时 func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { self.contentForSearchText(searchText: "", scope: -1)//初始化搜索 self.searchBar.showsScopeBar = false //隐藏辅助搜索栏 self.searchBar.text = "" //清空搜索文本 self.searchBar.sizeToFit() //加载适合的searchBar的大小 self.searchBar.resignFirstResponder()//放弃第一响应者的方式,关闭键盘 self.tableView.reloadData()//重新加载表视图数据 } //点击键盘上的Search(搜索按钮)时 func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { self.searchBar.showsScopeBar = false //隐藏辅助搜索栏 self.searchBar.sizeToFit() //加载适合的searchBar的大小 self.searchBar.resignFirstResponder()//放弃第一响应者的方式,关闭键盘 self.tableView.reloadData()//重新加载表视图数据 } //切换辅助搜索栏时 func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) { self.contentForSearchText(searchText: self.searchBar.text! as String as NSString, scope: selectedScope)//重新搜索 self.tableView.reloadData()//重新加载表视图数据 } /------------------------------------协议分割线-------------------------------------*/ //TableViewDataSource 协议方法实现 //返回表视图节的个数 override func numberOfSections(in tableView: UITableView) -> Int { // #warning Incomplete implementation, return the number of sections return 1 } //返回表视图每个节中的行数 override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // #warning Incomplete implementation, return the number of rows return self.SearchData.count } //返回每一个 自定义cell 的内容 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //请求可重用单元格,需要一个标识,CustomCellTableViewCell为自定义单元格类 let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) as! CustomCellTableViewCell //读取每一行的数据到字典中 let dict = self.SearchData[indexPath.row] as! NSDictionary //设置单元格中的主标题与图标 cell.myLabel?.text = dict["name"] as? String cell.myImageView?.image = UIImage(named: dict["image"] as! String) return cell } }
自定义的单元格(Cell)
import UIKit //-----------自定义的单元格(Cell) class CustomCellTableViewCell: UITableViewCell { @IBOutlet weak var myImageView: UIImageView! @IBOutlet weak var myLabel: 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 } }
添加索引与分组的表视图
import UIKit //--------------添加索引与分组的表视图 class IndexTableViewController: UITableViewController { var dictData: NSDictionary! //所有数据 var groupName: NSArray! //所有组的名称 override func viewDidLoad() { super.viewDidLoad() //获取plist文件路径 let plistPath = Bundle.main.path(forResource: "team_dictionary", ofType: "plist") //获取属性列表文件中的全部数据保存到pickerAllData中 self.dictData = NSDictionary(contentsOfFile: plistPath!) //无排序的小组名称数组 let listtemp = self.dictData.allKeys as NSArray //按照指定方法重新排序,这里是字母排序 self.groupName = listtemp.sortedArray(using: #selector(NSNumber.compare(_:))) as NSArray } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } //TableViewDataSource 协议方法实现 //返回表视图节的个数,所谓的分节 override func numberOfSections(in tableView: UITableView) -> Int { // #warning Incomplete implementation, return the number of sections return self.groupName.count } //返回表视图每个节中的行数 override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { //得到节的(组的)名称 let G_name = self.groupName[section] as! String //根据组名称得到:每组对应的数组 let G_dict = self.dictData[G_name] as! NSArray return G_dict.count } //返回每一个 自定义cell 的内容 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //请求可重用单元格,需要一个标识 indexdescet : 在视图中对应cell 中指定 let cell = tableView.dequeueReusableCell(withIdentifier: "indexdescet", for: indexPath) as UITableViewCell //得到节的索引 let section = indexPath.section //得到每一个节中 行的索引 let row = indexPath.row //得到节的(组的)名称 let G_name = self.groupName[section] as! String //根据组名称得到:每组对应的数组 let G_dict = self.dictData[G_name] as! NSArray //设置单元格中的主标题与图标 cell.textLabel?.text = G_dict[row] as? String return cell } /------------------------------------协议分割线-------------------------------------*/ //TableView索引的方法实现 //添加节标题,节标题默认是索引标题 override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { //得到节的(组的)名称 let G_name = self.groupName[section] as! String return G_name } //返回索引标题的集合(数组),右侧的索引列表 override func sectionIndexTitles(for tableView: UITableView) -> [String]? { //NSArray和NSMutableArray的区别就是后者是可变数组 var listitles = [String]() for item in self.groupName { let title = (item as AnyObject).substring(to: 1)//截取第一个字符 listitles.append(title)//添加到数组中 } return listitles } //分组:分组前需要先分节,然后在视图中 选中tableView标签指示器中的style进行选择 }
静态表视图,一般用于布局
import UIKit //----------静态表视图,一般用于布局 class StaticTableViewController: UITableViewController { //静态表:视图中选中tableView 选择静态,选择分组,设置节个数 override func viewDidLoad() { super.viewDidLoad() // Uncomment the following line to preserve selection between presentations // self.clearsSelectionOnViewWillAppear = false // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // MARK: - Table view data source //=======注:静态表的话,需要注释掉下面的方法,否则节与行全是0 /override func numberOfSections(in tableView: UITableView) -> Int { // #warning Incomplete implementation, return the number of sections return 0 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // #warning Incomplete implementation, return the number of rows return 0 }*/ }
删除,插入表视图
import UIKit //-------------删除,插入表视图 class DeleteAddTableViewController: UITableViewController { @IBOutlet var textField: UITextField! //在视图中非界面中的textField var jsonData = [String]() //一个空数组 override func viewDidLoad() { super.viewDidLoad() //通过代码实现导航控制器的右按钮,并已实现Done与Edit的切换, self.navigationItem.rightBarButtonItem = self.editButtonItem //加载时需要textField为隐藏状态 self.textField.isHidden = true //设置textDelegate为当前视图控制器: 拖拽吧 //设置数据(一般应该是请求接口得到的数据,这里就写死) self.jsonData = ["北京","河北","天津","上海","重庆","深圳","湖北","山东"] //dump(self.jsonData[0]) } //重写setEditng,点击Edit时会调用该方法 override func setEditing(_ editing: Bool, animated: Bool) { //调用父类的setEditing方法,需要父类中的一些默认操作 super.setEditing(editing, animated: animated) //调用tableView的setEditing方法,使表视图处于编辑状态 self.tableView.setEditing(editing, animated: animated) //editing = true 说明点击了Edit if editing { self.textField.isHidden = false }else{ self.textField.isHidden = true } //print(editing) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // MARK: - Table view data source //TableViewDataSource 协议方法实现 //返回表视图节的个数 override func numberOfSections(in tableView: UITableView) -> Int { // #warning Incomplete implementation, return the number of sections return 1 } //返回表视图每个节中的行数 override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.jsonData.count + 1 } //返回每一个 自定义cell 的内容 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //请求可重用单元格,需要一个标识,CustomCellTableViewCell为自定义单元格类 let cell = tableView.dequeueReusableCell(withIdentifier: "deleteandAdd", for: indexPath) //如果单元格的索引等于最后一条为 Add.. if indexPath.row == self.jsonData.count { //设置textField在Cell中的位置与大小 self.textField.frame = CGRect(x: 10, y: 0, width: 300, height: 66) //清空textField的内容 self.textField.text = "" //讲textField添加到Cell的contentView中 cell.contentView.addSubview(self.textField) }else{//为正常数据(Delete) //设置扩展视图的类型,就是Cell右侧的小箭头 cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator //设置单元的内容 cell.textLabel?.text = self.jsonData[indexPath.row] } return cell } //编辑风格,editingStyle参数会返回是insert还是delete,然后做对应的操作 override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) { //删除或添加单元格的Indexpath需要一个集合 let tempArray: [IndexPath] = [indexPath] if editingStyle == UITableViewCellEditingStyle.insert {//如果是插入 self.jsonData.append(self.textField.text!)//插入数据 self.tableView.insertRows(at: tempArray, with: UITableViewRowAnimation.left)//插入单元格 }else if editingStyle == UITableViewCellEditingStyle.delete {//如果是删 self.jsonData.remove(at: indexPath.row)//删除数据 self.tableView.deleteRows(at: tempArray, with: UITableViewRowAnimation.left)//删除单元格 } //UITableViewRowAnimation.left 为设置操作的动画,有很多动画可选择 } /------------------------------------协议分割线-------------------------------------*/ //TableViewDelegate 协议方法实现 //返回单元格在编辑状态下的样式,三种样式:none,insert,delete override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle { //如果单元格的索引等于最后一条为 Add.. if indexPath.row == self.jsonData.count { return UITableViewCellEditingStyle.insert }else{//为正常数据(Delete) return UITableViewCellEditingStyle.delete } } //设置单元格在点击后是否高亮 override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool { //如果单元格的索引等于最后一条为 Add.. 点击后不高亮 if indexPath.row == self.jsonData.count { return false }else{//为正常数据 点击后高亮 return true } } //设置单元格的高度,只能通过代码实现 override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { return 50 } }
移动单元格
import UIKit //---------------移动单元格 class MoveTableViewController: UITableViewController { var jsonData: NSMutableArray! //一个空数组 override func viewDidLoad() { super.viewDidLoad() //通过代码实现导航控制器的右按钮,并已实现Done与Edit的切换, self.navigationItem.rightBarButtonItem = self.editButtonItem //设置数据(一般应该是请求接口得到的数据,这里就写死) self.jsonData = NSMutableArray(array: ["PHP","ASP","JSP","JAVASCRIPT","SWIFT","PYTHON","PERL","C/C++","RUBY"]) //可变数组方式,移动单元格更适合用这种存储方式 /var newarr: NSMutableArray! newarr = NSMutableArray(array: ["一","二","三"]) newarr.removeObject(at: 0) //["二","三"] newarr.insert("一", at: 1) //["二","一","三"] print(newarr[1])*/ } //重写setEditng,点击Edit时会调用该方法 override func setEditing(_ editing: Bool, animated: Bool) { //调用父类的setEditing方法,需要父类中的一些默认操作 super.setEditing(editing, animated: animated) //调用tableView的setEditing方法,使表视图处于编辑状态 self.tableView.setEditing(editing, animated: animated) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } // MARK: - Table view data source //TableViewDataSource 协议方法实现 //返回表视图节的个数 override func numberOfSections(in tableView: UITableView) -> Int { // #warning Incomplete implementation, return the number of sections return 1 } //返回表视图每个节中的行数 override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.jsonData.count } //返回每一个 自定义cell 的内容 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //请求可重用单元格,需要一个标识,CustomCellTableViewCell为自定义单元格类 let cell = tableView.dequeueReusableCell(withIdentifier: "movecell", for: indexPath) //设置扩展视图的类型,就是Cell右侧的小箭头 cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator //设置单元的内容 cell.textLabel?.text = self.jsonData[indexPath.row] as? String return cell } //让你能够移动单元格 override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { return true } //在源索引路径上移动行,移动的一些操作 override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) { //得到要被移动的单元格数据 let cellName = self.jsonData[sourceIndexPath.row] //删掉要被移动的单元格数据 self.jsonData.removeObject(at: sourceIndexPath.row) //在移动的目录索引位置重新加入 要被移动的单元格数据 self.jsonData.insert(cellName, at: destinationIndexPath.row) //dump(self.jsonData) } /------------------------------------协议分割线-------------------------------------*/ //TableViewDelegate 协议方法实现 //返回单元格在编辑状态下的样式,三种样式:none,insert,delete override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle { return UITableViewCellEditingStyle.none //左侧不返回添加或删除标识 } }