类UItableVIEw表示一个列表视图,此视图可以显示列表,并且列表可以分为多个区间(section)。
显示列表假设一个案例:
显示计算机语言清单(["java","swift","Js"]和 *** 作系统的清单 ["windows","OS X","linux"]
这个清单在一个UItableVIEw上做分区显示,分为两个区间
那么代码如下:
import UIKit @UIApplicationMain class AppDelegate: UIResponder,UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication,dIDFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { self.window = UIWindow(frame: UIScreen.main.bounds) let page = Page() page.vIEw.backgroundcolor = .blue self.window!.rootVIEwController = page self.window?.makeKeyAndVisible() return true } } class Page: UIVIEwController { var a : table! overrIDe func vIEwDIDLoad() { super.vIEwDIDLoad() a = table() a.frame = CGRect(x: 0,y: 50,wIDth: 300,height: 500) self.vIEw.addSubvIEw(a) } } class table : UItableVIEw,UItableVIEwDataSource,UItableVIEwDelegate{ let sect = ["Lang","OS"] let lang = ["java","Js"] let os = ["windows","linux"] overrIDe init(frame: CGRect,style: UItableVIEwStyle) { super.init(frame:frame,style:style) self.dataSource = self self.delegate = self } required init?(coder aDecoder: NSCoder) { super.init(coder:aDecoder) } func numberOfSections(in: UItableVIEw) -> Int { return 2 } func tableVIEw(_ tableVIEw: UItableVIEw,vIEwForheaderInSection section: Int) -> UIVIEw? { let rect = CGRect(x: 0,y: 0,wIDth: tableVIEw.frame.size.wIDth,height: 44) let footerVIEw = UILabel(frame:rect) footerVIEw.text = sect[section] return footerVIEw } func tableVIEw(_ tableVIEw: UItableVIEw,heightForheaderInSection section: Int) -> CGfloat { return 44 } func tableVIEw(_ tableVIEw: UItableVIEw,numberOfRowsInSection section: Int) -> Int { return section == 0 ?lang.count:os.count } func tableVIEw(_ tableVIEw: UItableVIEw,cellForRowAt indexPath: IndexPath) -> UItableVIEwCell { let arr = indexPath.section == 0 ? lang:os let a = UItableVIEwCell(style: .default,reuseIDentifIEr: nil) a.textLabel?.text = String(describing:arr[indexPath.row]) return a } }
代码创建了三个类,其中的AppDelegate和之前的并没有什么不同,Page继承于UIVIEwController,也和之前的代码类似,只是在载入时把table作为子视图加入进来。要特别介绍的是table。
table继承于UItableVIEw,并实现UItableVIEwDataSource,UItableVIEwDelegate,在配合代码:
self.dataSource = self self.delegate = self
就指明了UItableVIEw的数据源对象为table,委托对象也是table。前者指明此对象是UItableVIEw的数据提供者,后者指明此对象是UItableVIEw的外观和行为的提供者。
具体数据提供的方法就是在此类内实现方法:
func numberOfSections(in: UItableVIEw) -> Int { return 2 } func tableVIEw(_ tableVIEw: UItableVIEw,reuseIDentifIEr: nil) a.textLabel?.text = String(describing:arr[indexPath.row]) return a }
第一个方法告诉tableVIEw此列表共有两个区间要去显示。第二个方法告诉tableVIEw此列表每个区间的行数,第三个方法告诉tableVIEw指定的区间和行数的内容是什么。
作为UItableVIEw的外观和行为的提供者,具体体现是实现了这些方法:
func tableVIEw(_ tableVIEw: UItableVIEw,heightForheaderInSection section: Int) -> CGfloat { return 44 }
第一个方法为指定的区间创建一个头视图,第二个方法指示指定区间的行高。
协议UItableVIEwDataSource,UItableVIEwDelegate还有很多可以实现的方法,具体参考iOS的开发者参考资料。
添加删除修改类UItableVIEw不但可以显示内容,还可以配合很多 *** 作。这些内容的 *** 作的基本流程就是修改数据源,然后通知tableVIEw重新装入。代码入下:
import UIKit @UIApplicationMain class AppDelegate: UIResponder,height: 500) self.vIEw.addSubvIEw(a) } } class table : UItableVIEw,UItableVIEwDelegate{ var sect = NSMutableArray.init(array: ["Lang","OS"]) var lang = NSMutableArray.init(array: ["java","Js"]) var os = NSMutableArray.init(array:["windows","linux"]) var t = Timer() var count = 0 overrIDe init(frame: CGRect,style:style) self.dataSource = self self.delegate = self t.invalIDate() t = Timer.scheduledTimer(timeInterval: 1,target: self,selector: #selector(self.update),userInfo: nil,repeats: true); } required init?(coder aDecoder: NSCoder) { super.init(coder:aDecoder) } func update() { if count == 0 { os[0] = "Win" }else if count == 1 { os.add("FreeBSD") }else if count == 2 { lang.removeObject(at: 0) } count += 1 if count >= 3 { t.invalIDate() } self.reloadData() } func numberOfSections(in: UItableVIEw) -> Int { return sect.count } func tableVIEw(_ tableVIEw: UItableVIEw,height: 44) let footerVIEw = UILabel(frame:rect) footerVIEw.text = String(describing: sect[section]) return footerVIEw } func tableVIEw(_ tableVIEw: UItableVIEw,cellForRowAt indexPath: IndexPath) -> UItableVIEwCell { let arr = indexPath.section == 0 ? lang as NSArray :os as NSArray let a = UItableVIEwCell(style: .default,reuseIDentifIEr: nil) a.textLabel?.text = String(describing:arr[indexPath.row]) return a } }
此代码和上一节的代码相比,不同在于:
之前的计算机语言数组和 *** 作系统数据被改成了可变的数组,因为在这个代码中,我们需要修改数据来验证对UItableVIEw的修改
在table的init函数内,创建一个Timer,它每秒激发一个定时器事件,在不同的激发次数中,分别对数据做修改、添加、删除
调用reload方法,从而让UItableVIEw重新加载数据
默认提供的删除和列表重排可以自己添加按钮并执行对UItableVIEw的列表的删除和重排。但是也可以使用它自己提供了删除和重排的UI。删除流程是这样的:
用户设置UItableVIEw为编辑模式
系统在当前内容的基础上,加上删除按钮(内容左侧,红色的减号图标),以及重排按钮(内容右侧)
用户可以选择点击删除按钮,系统向左推移内容,显示一个delete按钮
用户点击delete按钮,系统就会调用程序员实现的委托对象的函数:func tableVIEw(_ tableVIEw: UItableVIEw,commit editingStyle: UItableVIEwCellEditingStyle,forRowAt indexPath:
IndexPath)
重排流程是这样的:
用户设置UItableVIEw为编辑模式
系统在当前内容的基础上,加上删除按钮(内容左侧,红色的减号图标),以及重排按钮(内容右侧)
用户可以选择按住拖动重排按钮,系统可视化这样拖动过程
用户拖动完成,系统就会调用程序员实现的委托对象的函数: func tableVIEw(_ tableVIEw: UItableVIEw,moveRowAt sourceIndexPath: IndexPath,to destinationIndexPath: IndexPath)
代码如下:
import UIKit @UIApplicationMain class AppDelegate: UIResponder,dIDFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { self.window = UIWindow(frame: UIScreen.main.bounds) let page = Page() page.vIEw.backgroundcolor = .blue self.window!.rootVIEwController = page self.window?.makeKeyAndVisible() return true } } class Page: UIVIEwController { var a : LangtableRowOper1? overrIDe func vIEwDIDLoad() { super.vIEwDIDLoad() a = LangtableRowOper1() a!.frame = CGRect(x: 0,y: 200,height: 200) self.vIEw.addSubvIEw(a!) let b = UIbutton() b.setTitle("edit",for: UIControlState()) b.backgroundcolor = UIcolor.red b.addTarget(self,action: #selector(VIEwController.edit(_:)),for: .touchDown) let e = UIbutton() e.setTitle("Done",for: UIControlState()) e.backgroundcolor = UIcolor.blue e.addTarget(self,action: #selector(Page.done(_:)),for: .touchDown) let sv = UIStackVIEw() sv.backgroundcolor = UIcolor.gray sv.axis = UILayoutConstraintAxis.horizontal sv.distribution = .equalCentering; sv.alignment = .center; sv.spacing = 10; sv.frame = CGRect(x: 0,y: 100,height: 50) sv.addArrangedSubvIEw(b) sv.addArrangedSubvIEw(e) sv.translatesautoresizingMaskIntoConstraints = true self.vIEw.addSubvIEw(sv) } func edit( _ b : UIbutton!){ a!.setEditing(true,animated: true) } func done( _ b : UIbutton!){ a!.setEditing(false,animated: true) } } class table : UItableVIEw,UItableVIEwDelegate{ var arr = NSMutableArray.init(array: ["java","Js"]) overrIDe init(frame: CGRect,style:style) self.dataSource = self self.delegate = self } required init?(coder aDecoder: NSCoder) { super.init(coder:aDecoder) } func tableVIEw(_ tableVIEw: UItableVIEw,numberOfRowsInSection section: Int) -> Int { return arr.count } func tableVIEw(_ tableVIEw: UItableVIEw,cellForRowAt indexPath: IndexPath) -> UItableVIEwCell { let a = UItableVIEwCell(style: .default,reuseIDentifIEr: nil) a.textLabel?.text = String(describing: arr[indexPath.row]) return a } func tableVIEw(_ tableVIEw: UItableVIEw,forRowAt indexPath: IndexPath) { if editingStyle == .delete{ arr.removeObject(at: indexPath.row) // http://stackoverflow.com/questions/21870680/invalID-update-invalID-number-of-rows-in-section-0 self.deleteRows(at: [indexPath],with: UItableVIEwRowAnimation.fade) } } func tableVIEw(_ tableVIEw: UItableVIEw,canMoveRowAt indexPath: IndexPath) -> Bool { return true; } func tableVIEw(_ tableVIEw: UItableVIEw,to destinationIndexPath: IndexPath) { let s = sourceIndexPath.row let d = destinationIndexPath.row let temp = arr[s] arr.removeObject(at: s) arr.insert(temp,at: d) } }
注意,代码中:
func tableVIEw(_ tableVIEw: UItableVIEw,canMoveRowAt indexPath: IndexPath) -> Bool { return true; }
此函数需要实现,从而告诉UItableVIEw那些行是可以拖动重排的。这里全部返还true,表示所有内容都可以重排。
tableVIEw的装饰界面除了显示section和row之外,tableVIEw可以加入表头表位,节头节尾,帮助程序员更好的组织内容。
我们现在来展示了一个有两个section,每个section有行的界面。通过代码加入了表头表尾、节头节尾。如下:
import UIKit@UIApplicationMainclass AppDelegate: UIResponder,UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication,dIDFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { self.window = UIWindow(frame: UIScreen.main.bounds) let page = Page() page.vIEw.backgroundcolor = .blue self.window!.rootVIEwController = page self.window?.makeKeyAndVisible() return true }}class table : UItableVIEw,UItableVIEwDataSource{ let arrs = [["Row 1","Row 2"],["Row 1"]] let Titles = ["Section Title 1","Section Title 2"] let footers = ["Section Footer 1","Section Footer 2"] let tableheader = "table header" let tablefooter = "table Footer" convenIEnce init(){ self.init(frame: CGRect.zero,style:UItableVIEwStyle.grouped) } overrIDe init(frame: CGRect,style: UItableVIEwStyle) { super.init(frame:frame,style:style) self.dataSource = self self.tableheaderVIEw = UIVIEw() self.tableheaderVIEw!.frame = CGRect(x: 0,wIDth: 200,height: 20) let l = UILabel() l.text = tableheader l.frame = CGRect(x: 0,height: 20) self.tableheaderVIEw?.addSubvIEw(l) self.tableFooterVIEw = UIVIEw() self.tableFooterVIEw!.frame = CGRect(x: 0,height: 20) let f = UILabel() f.text = tablefooter f.frame = CGRect(x: 0,height: 20) self.tableFooterVIEw?.addSubvIEw(f) } required init?(coder aDecoder: NSCoder) { super.init(coder:aDecoder) } func tableVIEw(_ tableVIEw: UItableVIEw,numberOfRowsInSection section: Int) -> Int { return arrs[section].count } func tableVIEw(_ tableVIEw: UItableVIEw,cellForRowAt indexPath: IndexPath) -> UItableVIEwCell{ let a = UItableVIEwCell(style: UItableVIEwCellStyle.value1,reuseIDentifIEr: nil) a.textLabel?.text = String(arrs[indexPath.section][indexPath.row]) return a } func numberOfSections(in tableVIEw: UItableVIEw) -> Int{ return arrs.count } func tableVIEw(_ tableVIEw: UItableVIEw,TitleForheaderInSection section: Int) -> String?{ return Titles[section] } func tableVIEw(_ tableVIEw: UItableVIEw,TitleForFooterInSection section: Int) -> String?{ return footers[section] }}class Page: UIVIEwController { var a : table! overrIDe func vIEwDIDLoad() { super.vIEwDIDLoad() a = table() a.frame = CGRect(x: 0,y: 30,height: 400) self.vIEw.addSubvIEw(a) }}
这里比较特别的是,函数
func tableVIEw(_ tableVIEw: UItableVIEw,TitleForheaderInSection section: Int) -> String?{ return Titles[section] }
告诉tableVIEw,每个指定section的头标题。
func tableVIEw(_ tableVIEw: UItableVIEw,TitleForFooterInSection section: Int) -> String?{ return footers[section] }
告诉tableVIEw,每个指定section的尾标题。
标记类UItableVIEw支持对每个行做标记和取消标记,标记可以有多种。其中比较常用的是打对号图标。如下代码,演示了如何对每个行打对号和取消打对号:
import UIKit @UIApplicationMain class AppDelegate: UIResponder,dIDFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { self.window = UIWindow(frame: UIScreen.main.bounds) let page = Page() page.vIEw.backgroundcolor = .blue self.window!.rootVIEwController = page self.window?.makeKeyAndVisible() return true } } class table : UItableVIEw,UItableVIEwDelegate{ let arr = ["java","Js"] overrIDe init(frame: CGRect,numberOfRowsInSection section: Int) -> Int { return arr.count } func tableVIEw(_ tableVIEw: UItableVIEw,reuseIDentifIEr: nil) a.textLabel?.text = String(arr[indexPath.row]) return a } func tableVIEw(_ tableVIEw: UItableVIEw,dIDSelectRowAt indexPath: IndexPath){ print("dID select \(indexPath.row)") self.deselectRow(at: indexPath,animated: false) if self.cellForRow(at: indexPath)?.accessoryType != .checkmark{ self.cellForRow(at: indexPath)?.accessoryType = .checkmark }else{ self.cellForRow(at: indexPath)?.accessoryType = .none } } } class Page: UIVIEwController { var a : table! overrIDe func vIEwDIDLoad() { super.vIEwDIDLoad() a = table() a.frame = CGRect(x: 0,height: 400) self.vIEw.addSubvIEw(a) } }
运行起来后,可看到三个行,点击任何一个行都会显示对号标记在行尾,再点击一次就会取消此标记。查询UItableVIEwCellAccessoryType的官方文档可以得到更多的标记类型。
重用cell创建在之前的代码中,每次调用到函数:
func tableVIEw(_ tableVIEw: UItableVIEw,cellForRowAt indexPath: IndexPath) -> UItableVIEwCell
需要一个UItableVIEwCell实例时,都是采用临时创建的方式。如果创建的UItableVIEwCell实例比较多时,可以通过重用已经创建的UItableVIEwCell实例来提高效率。做法就是:
注册一个UItableVIEwCell类,指定其的重用标识符
通过重用标识符创建实例
UIKit会在内部对此过程优化。实例代码如下:
import UIKit @UIApplicationMain class AppDelegate: UIResponder,dIDFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { self.window = UIWindow(frame: UIScreen.main.bounds) let page = Page() page.vIEw.backgroundcolor = .blue self.window!.rootVIEwController = page self.window?.makeKeyAndVisible() return true } } class table: UItableVIEw,UItableVIEwDataSource{ let arr = ["JavaScript","delphi"] let MyIDentifIEr = "cell" overrIDe init(frame: CGRect,style:style) self.dataSource = self self.register(UItableVIEwCell.self,forCellReuseIDentifIEr: MyIDentifIEr) } required init?(coder aDecoder: NSCoder) { super.init(coder:aDecoder) } func tableVIEw(_ tableVIEw: UItableVIEw,cellForRowAt indexPath: IndexPath) -> UItableVIEwCell { let a = tableVIEw.dequeueReusableCell(withIDentifIEr: MyIDentifIEr)! a.textLabel?.text = String(arr[indexPath.row]) return a } } class Page: UIVIEwController { var a : table! overrIDe func vIEwDIDLoad() { super.vIEwDIDLoad() a = table() a.frame = CGRect(x: 0,height: 400) self.vIEw.addSubvIEw(a) } }复合的Cell
之前的代码,创建的Cell都是简单文字;实际上,每个Cell都可以作为一个容器,装入更多的元素。如下代码展示了一个复合的Cell的创建:
import UIKit @UIApplicationMain class AppDelegate: UIResponder,UItableVIEwDataSource{ let arr = ["java","Js"] overrIDe init(frame: CGRect,style: UItableVIEwStyle) { super.init(frame:frame,style:style) self.dataSource = self } required init?(coder aDecoder: NSCoder) { super.init(coder:aDecoder) } func tableVIEw(_ tableVIEw: UItableVIEw,numberOfRowsInSection section: Int) -> Int { return arr.count } func tableVIEw(_ tableVIEw: UItableVIEw,cellForRowAt indexPath: IndexPath) -> UItableVIEwCell { let a = UItableVIEwCell(style: .default,reuseIDentifIEr: nil) a.textLabel?.text = String(arr[indexPath.row]) let s = UISwitch() s.frame = CGRect(x: 0,wIDth: 20,height: 20) s.addTarget(self,action: #selector(table.action(_:)),for: .valueChanged) s.isOn = true a.accessoryVIEw = s return a } func action(_ sender : UISwitch!){ print(sender.isOn) } } class Page: UIVIEwController { var a : table! overrIDe func vIEwDIDLoad() { super.vIEwDIDLoad() a = table() a.frame = CGRect(x: 0,height: 400) self.vIEw.addSubvIEw(a) } }
本案例在每个Cell中添加了一个UISwitch按钮,并且可以如同一般的UIVIEw一样的响应此按钮的事件。
默认的Cell风格可以不必自己定制Cell样式,而是直接使用系统提供的,这样你可以通过设置不同的UItableVIEwCellAccessoryType、文字、文字1、图片、UItableVIEwCellStyle而让Cell外观变得丰富多彩:
import UIKit @UIApplicationMain class AppDelegate: UIResponder,dIDFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { self.window = UIWindow(frame: UIScreen.main.bounds) let page = Page() page.vIEw.backgroundcolor = .blue self.window!.rootVIEwController = page self.window?.makeKeyAndVisible() return true } }
class Page: UIVIEwController { var a : table! overrIDe func vIEwDIDLoad() { super.vIEwDIDLoad() a = table() a.frame = CGRect(x: 0,height: 400) self.vIEw.addSubvIEw(a) } }
class Row { var text : String = "" var text2 : String = "" var image : UIImage var access : UItableVIEwCellAccessoryType var style : UItableVIEwCellStyle init( text : String,text2:String,image:UIImage,access:UItableVIEwCellAccessoryType,style : UItableVIEwCellStyle){ self.text = text self.text2 = text2 self.image = image self.access = access self.style = style } } class table: UItableVIEw,UItableVIEwDataSource{ let arr = [ Row( text:"java",text2:"old plain",image:UIImage.imageWithcolor(UIcolor.red),access:UItableVIEwCellAccessoryType.checkmark,style: UItableVIEwCellStyle.value1),Row( text:"ruby",text2:"new cool slow",image:UIImage.imageWithcolor(UIcolor.green),access:UItableVIEwCellAccessoryType.detailbutton,style: UItableVIEwCellStyle.value2),Row( text:"swift",text2:"new cool quick ",image:UIImage.imageWithcolor(UIcolor.blue),access:UItableVIEwCellAccessoryType.detaildisclosurebutton,style: UItableVIEwCellStyle.subTitle) ] overrIDe init(frame: CGRect,style:style) self.dataSource = self } required init?(coder aDecoder: NSCoder) { super.init(coder:aDecoder) } func tableVIEw(_ tableVIEw: UItableVIEw,cellForRowAt indexPath: IndexPath) -> UItableVIEwCell { let a = UItableVIEwCell(style: arr[indexPath.row].style,reuseIDentifIEr: nil) a.textLabel?.text = arr[indexPath.row].text a.detailTextLabel?.text = arr[indexPath.row].text2 a.imageVIEw?.image = arr[indexPath.row].image a.accessoryType = arr[indexPath.row].access return a } } extension UIImage { class func imageWithcolor(_ color: UIcolor) -> UIImage { let rect = CGRect(x: 0.0,y: 0.0,wIDth: 10.0,height: 10.0 ) UIGraphicsBeginImageContext(rect.size) let context = UIGraphicsGetCurrentContext() context?.setFillcolor(color.cgcolor) context?.fill(rect) let image = UIGraphicsGetimageFromCurrentimageContext() UIGraphicsEndImageContext() return image! } }
案例显示了三行,每行有不同的风格组合,都是通过设置UItableVIEwCellAccessoryType、文字、文字1、图片、UItableVIEwCellStyle来达成的。你可以实际运行此代码,了解不同样式的差异。可以通过官方手册查询UItableVIEwCellStyle和UItableVIEwCellAccessoryType的不同选择。这里列出的类为UIImage扩展出来的方法:
class func imageWithcolor(_ color: UIcolor) -> UIImage
是为了不必寻找图片,而可以即席按需创建出可以用于实例的图片,传递不同的颜色值,可以得到不同颜色的小方块图片。我们只是需要展示Cell的显示图片的能力,因此只有通过代码创建出图就好,不必为此单独寻找适合工程使用的图片。
UItableVIEwController我们一直使用UItableVIEw,把它加入到一个VIEwController内,然后由AppDelegate加载后者。实际上,可以使用UItableVIEwController直接由AppDelegate加载:
import UIKit @UIApplicationMain class AppDelegate: UIResponder,dIDFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { self.window = UIWindow(frame: UIScreen.main.bounds) let page = LangtableVIEwController() page.vIEw.backgroundcolor = .blue self.window!.rootVIEwController = page self.window?.makeKeyAndVisible() return true } } class LangtableVIEwController : UItableVIEwController{ let arr = ["swift","obj-c","ruby"] let MyIDentifIEr = "cell" overrIDe func vIEwDIDLoad() { super.vIEwDIDLoad() tableVIEw.register(UItableVIEwCell.self,forCellReuseIDentifIEr: MyIDentifIEr) } overrIDe func tableVIEw(_ tableVIEw: UItableVIEw,numberOfRowsInSection section: Int) -> Int { return arr.count } overrIDe func tableVIEw(_ tableVIEw: UItableVIEw,cellForRowAt indexPath: IndexPath) -> UItableVIEwCell { let a = tableVIEw.dequeueReusableCell(withIDentifIEr: MyIDentifIEr) a!.textLabel?.text = arr[indexPath.row] return a! } }
和UItableVIEw的使用的不同之处,在于:
本来需要实现UItableVIEwDataSource和UItableVIEwDelegate的方法,现在已经有UItableVIEwController实现,作为UItableVIEwController的子类,新类需要的是覆盖父类的方法。
使用UItableVIEwController会自动把UItableVIEw填满AppDelegate.window视图内。无需程序员指定位置和大小。
总结以上是内存溢出为你收集整理的Swift iOS: UITableView的使用全部内容,希望文章能够帮你解决Swift iOS: UITableView的使用所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)