UIKit-建立一個簡單的表格式App

UIKit-建立一個簡單的表格式App

  • 先將模擬器設成手機的
  • 到元件庫拉一個Table View
  • 將元件佈滿整個視圖

不過現在看起應該是空白的

先點選左邊的 Table View
在點右邊的 Prototype Cells 把 0 改成 1

這時候應該就會出現一個cell
點擊 cell 並在右側的 Identifier 填入 datacell 這是cell的名字

可以測試一下模擬器…

開始寫程式

先在 UIViewController 後面加兩個協定:

  • UITableViewDataSource
  • UITableViewDelegate

在加入這兩個協定後,應該會出現錯誤訊息

那是使用DataSource時,還需要兩個方法來輔助它:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
}

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

按下錯誤訊息的Fix 方法就會出現了。

宣告一個變數來儲存表格資料(餐廳名稱)

變數名稱為『 restaurantNames 』:


class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
    var restaurantNames = ["Cafe Deadend", "Homei", "Teakha", "Cafe Loisl", "Petite Oyster", "For Kee Restaurant", "Po's     Atelier", "Bourke Street Bakery", "Haigh's Chocolate", "Palomino Espresso", "Upstate", "Traif", "Graham Avenue Meats     And Deli", "Waffle & Wolf", "Five Leaves", "Cafe Lore", "Confessional", "Barrafina", "Donostia","Royal Oak", "CASK       Pub and Kitchen"]
    
    ...
}

設定DataSource的兩個方法

第一個方法:count

利用 count方法來取得 restaurantNames 的項目數


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return restaurantNames.count
    }

第二個方法:

每次表格要顯示時都會被呼叫

從 indexPath 物件中,我們可以取得目前正在顯示的 indexPath.row


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cellIdentifier = "datacell"
        let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)

        cell.textLabel?.text = restaurantNames[indexPath.row]
    
        return cell
    }

cell.textLabel?.text = restaurantNames[indexPath.row]
指定 Label 要顯示的文字

Optional:
textLabel是一個Optional,要存取textLabel的屬性,必須先確定是否有值。除了可以用if let來進行確認之外,另外就是在textLabel後面加上一個問號(?)

  • dequeueReusableCell 是什麼?

這個方法是用來指定 datacell 試別碼來取得佇列(queue)中可以再利用的表格(cell)

  • cellIdentifier

可以回收cell以提高性能
cellIdentifier用於獲取正確的緩存cell
而不是另闢一個cell
多闢一個cell記憶體就多一點負擔

連結 DataSource 與 Delegate

將 UITableViewDataSource, UITableViewDelegate 這兩個協定寫入程,就還做一件事才可以讓協定起作用,這個動作是要讓Storyboard的UITableView物件知道協定是來自於ViewController。

回到 Main.Storyboard 按右鍵選取 Table View 按住不放

拖到 View Controller上,放開後會有選單出現

點一下 dataSource ,點下去之後前面會有個小點點

再重覆同樣的動作,點delegate

然後點一下 Table View並按右鍵,以查看是否有連結:

現在測試畫面是否正常

在文字前面加縮圖

圖片

將圖片放到 Assets.xcassets

在 cellForRowAt方法裡寫行程式:
寫一行程式``
cell.textLabel?.text = restaurantNames[indexPath.row]

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cellIdentifier = "datacell"
        let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)

        cell.textLabel?.text = restaurantNames[indexPath.row]
        cell.imageView?.image = UIImage(named: restaurantNames[indexPath.row])

        return cell
    }

隱藏狀態列

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    ...
    ...
    
    //可以隱藏狀態列
    override var prefersStatusBarHidden:Bool {
        return true
    }
}

顯示不同圖片

很多圖片

加上一行程式碼:

cell.imageView?.image = UIImage(named: restaurantNames[indexPath.row])

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cellIdentifier = "datacell"
        let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)

        cell.textLabel?.text = restaurantNames[indexPath.row]
        cell.imageView?.image = UIImage(named: restaurantNames[indexPath.row])

        return cell
    }

完整程式碼


import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
    var restaurantNames = ["Cafe Deadend", "Homei", "Teakha", "Cafe Loisl", "Petite Oyster", "For Kee Restaurant", "Po's Atelier", "Bourke Street Bakery", "Haigh's Chocolate", "Palomino Espresso", "Upstate", "Traif", "Graham Avenue Meats And Deli", "Waffle & Wolf", "Five Leaves", "Cafe Lore", "Confessional", "Barrafina", "Donostia","Royal Oak", "CASK Pub and Kitchen"]
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return restaurantNames.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cellIdentifier = "datacell"
        let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)

        cell.textLabel?.text = restaurantNames[indexPath.row]
        cell.imageView?.image = UIImage(named: restaurantNames[indexPath.row])

        return cell
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
    //可以隱藏狀態列
    override var prefersStatusBarHidden:Bool {
        return true
    }
}