Swift iOS: UITableView的使用

1000copy發表於2017-02-28

類UITableView表示一個列表檢視,此檢視可以顯示列表,並且列表可以分為多個區間(section)。

顯示列表

假設一個案例:

  1. 顯示計算機語言清單([“java”,”swift”,”js”]和作業系統的清單 [“Windows”,”OS X”,”Linux”]

  2. 這個清單在一個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","swift","js"]
        let os = ["Windows","OS X","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, 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
        }
        

第一個方法告訴TableView此列表共有兩個區間要去顯示。第二個方法告訴TableView此列表每個區間的行數,第三個方法告訴TableView指定的區間和行數的內容是什麼。

作為UITableView的外觀和行為的提供者,具體體現是實現了這些方法:

        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
        }
        

第一個方法為指定的區間建立一個頭檢視,第二個方法指示指定區間的行高。

協議UITableViewDataSource,UITableViewDelegate還有很多可以實現的方法,具體參考iOS的開發者參考資料。

新增刪除修改

類UITableView不但可以顯示內容,還可以配合很多操作。這些內容的操作的基本流程就是修改資料來源,然後通知TableView重新裝入。程式碼入下:

    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{
        var sect = NSMutableArray.init(array: ["Lang","OS"])
        var lang = NSMutableArray.init(array: ["java","swift","js"])
        var os = NSMutableArray.init(array:["Windows","OS X","Linux"])
        var t = Timer()
        var count  = 0
        override init(frame: CGRect, style: UITableViewStyle) {
            super.init(frame:frame,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, 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 = String(describing: 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  as NSArray :os  as NSArray
            let a = UITableViewCell(style: .default, reuseIdentifier: nil)
            a.textLabel?.text = String(describing:arr[indexPath.row])
            return a
        }
    }

此程式碼和上一節的程式碼相比,不同在於:

  1. 之前的計算機語言陣列和作業系統資料被改成了可變的陣列,因為在這個程式碼中,我們需要修改資料來驗證對UITableView的修改

  2. 在Table的init函式內,建立一個Timer,它每秒激發一個定時器事件,在不同的激發次數中,分別對資料做修改、新增、刪除

  3. 呼叫reload方法,從而讓UITableView重新載入資料

預設提供的刪除和列表重排

可以自己新增按鈕並執行對UITableView的列表的刪除和重排。但是也可以使用它自己提供了刪除和重排的UI。刪除流程是這樣的:

  1. 使用者設定UITableView為編輯模式

  2. 系統在當前內容的基礎上,加上刪除按鈕(內容左側,紅色的減號圖示),以及重排按鈕(內容右側)

  3. 使用者可以選擇點選刪除按鈕,系統向左推移內容,顯示一個delete按鈕

  4. 使用者點選delete按鈕,系統就會呼叫程式設計師實現的委託物件的函式:func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath:
    IndexPath)

重排流程是這樣的:

  1. 使用者設定UITableView為編輯模式

  2. 系統在當前內容的基礎上,加上刪除按鈕(內容左側,紅色的減號圖示),以及重排按鈕(內容右側)

  3. 使用者可以選擇按住拖動重排按鈕,系統視覺化這樣拖動過程

  4. 使用者拖動完成,系統就會呼叫程式設計師實現的委託物件的函式: func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)

程式碼如下:

    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 : LangTableRowOper1?
        override func viewDidLoad() {
            super.viewDidLoad()
            a  = LangTableRowOper1()
            a!.frame = CGRect(x: 0,y: 200,width: 300,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,width: 300,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,UITableViewDataSource,UITableViewDelegate{
        var arr = NSMutableArray.init(array: ["java","swift","js"])
        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 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, commit editingStyle: UITableViewCellEditingStyle, 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, moveRowAt sourceIndexPath: IndexPath, 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
@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 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, y: 0,width: 200,height: 20)
        let l = UILabel()
        l.text = tableheader
        l.frame = CGRect(x: 0, y: 0,width: 200,height: 20)
        self.tableHeaderView?.addSubview(l)
        
        self.tableFooterView = UIView()
        self.tableFooterView!.frame = CGRect(x: 0, y: 0,width: 200,height: 20)
        let f = UILabel()
        f.text = tablefooter
        f.frame = CGRect(x: 0, y: 0,width: 200,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,width: 300,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, 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,UITableViewDelegate{
        let arr = ["java","swift","js"]
        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 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])
            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,y: 30,width: 300,height: 400)
            self.view.addSubview(a)
        }
    }

執行起來後,可看到三個行,點選任何一個行都會顯示對號標記在行尾,再點選一次就會取消此標記。查詢UITableViewCellAccessoryType的官方文件可以得到更多的標記型別。

重用cell建立

在之前的程式碼中,每次呼叫到函式:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

需要一個UITableViewCell例項時,都是採用臨時建立的方式。如果建立的UITableViewCell例項比較多時,可以通過重用已經建立的UITableViewCell例項來提高效率。做法就是:

  1. 註冊一個UITableViewCell類,指定其的重用識別符號

  2. 通過重用識別符號建立例項

UIKit會在內部對此過程優化。例項程式碼如下:

    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 Table: UITableView,UITableViewDataSource{
        let arr = ["javascript","delphi"]
        let MyIdentifier = "cell"
        override init(frame: CGRect, style: UITableViewStyle) {
            super.init(frame:frame,style:style)
            self.dataSource = self
            self.register(UITableViewCell.self, forCellReuseIdentifier: MyIdentifier)
        }
        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 = 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,y: 30,width: 300,height: 400)
            self.view.addSubview(a)
        }
    }

複合的Cell

之前的程式碼,建立的Cell都是簡單文字;實際上,每個Cell都可以作為一個容器,裝入更多的元素。如下程式碼展示了一個複合的Cell的建立:

    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 Table : UITableView,UITableViewDataSource{
            let arr = ["java","swift","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,y: 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,y: 30,width: 300,height: 400)
            self.view.addSubview(a)
        }
    }

本案例在每個Cell中新增了一個UISwitch按鈕,並且可以如同一般的UIView一樣的響應此按鈕的事件。

預設的Cell風格

可以不必自己定製Cell樣式,而是直接使用系統提供的,這樣你可以通過設定不同的UITableViewCellAccessoryType、文字、文字1、圖片、UITableViewCellStyle而讓Cell外觀變得豐富多彩:

    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: 30,width: 300,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: 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: 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, UIApplicationDelegate {
        var window: UIWindow?
        func application(_ application: UIApplication, 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的使用的不同之處,在於:

  1. 本來需要實現UITableViewDataSource和UITableViewDelegate的方法,現在已經有UITableViewController實現,作為UITableViewController的子類,新類需要的是覆蓋父類的方法。

  2. 使用UITableViewController會自動把UITableView填滿AppDelegate.window檢視內。無需程式設計師指定位置和大小。

相關文章