在这一章中学习主要学习到了表视图的应用,普通表视图,表视图的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 //左侧不返回添加或删除标识
}
}