iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 18
1
自我挑戰組

Hey! UIKit, 做個朋友吧~系列 第 18

Day 18: 來自深淵-UITableView(III)

在把data放進table之前,先跟大家講解一個重要的觀念:reuse。

在沒有reuse之前,一筆資料一個row就開一個cell,但如果有1000筆資料怎麼辦?開1000個cell非常的浪費記憶體空間,同時也影響了app的效能。工程師就想到:反正我開1000個cell,螢幕也無法同時顯示這麼多個,那不如讓cell可以被重複利用。

於是就想出下圖這個方法:

(圖片來源:iOS Performance Tricks To Make Your App Feel More Performant)

當手機螢幕上下滑動,沒入螢幕邊緣的cell就會進到一個佇列裡,而同時間會從佇列叫出cell供滑動出現的表格列使用。

這麼一來cell就可以被重複使用,即便我有1000筆資料,也只需要準備與手機螢幕符合的cell數量即可,而關於這點你只要呼叫相對應的function,符合螢幕的cell數swift自己會幫你handle。

Register

接下來來講講怎麼把資料裝進table裡。

要把資料裝進table,首先要設計一個cell,並且可以供table使用。
swift提供了register(_:forCellReuseIdentifier:)這個方法,讓你可以依據cell的名字註冊一個cell給table,而可以被註冊的只有:

  • UINib
  • UITableViewCell及其子類別

之前範例看到的不同形式的cell,其實就是UITableViewCell裡面提供的內建形式,現在我們來實作看看。

首先創建一個UITableViewCell的子類別。

接下來設計cell裡面的格式,我們加了一個image和一個label,並把它取名叫adventureCell,這部分因為與UITableView裡的function不相關,我就先不實作程式碼了。

然後在tableView裡註冊這個cell:

newTableView.register(UITableViewCell.self, forCellReuseIdentifier: "adventureCell")

這麼一來table就可以使用這個cell了。

而swift同樣也提供了register(_:forHeaderFooterViewReuseIdentifier:)這個function供table註冊UINib或UITableViewHeaderFooterView供header/footer使用,實作的方法相同。

Reuse

cell已經被table註冊了,接下來就是要決定cell的使用位置與時機。
這個需要使用dequeueReusableCell(withIdentifier:for:),搭配dataSource的tableView(_:cellForRowAt:)來對每一個indexPath的row做指定。
其實我們在class採用dataSource時就已經實作過dequeueReusableCell(withIdentifier:for:),這個function就是在table裡使用會存入佇列的可重複使用的cell,並使用identidier指定cell的形式。

那我們現在實作這個function。首先建立一筆資料:

var adventureCharacters = ["Finn", "Jack", "Beemo", "Princess Bubblegum", "Marceline", "Ice King"]

接下來定義dataSource的tableView(_:cellForRowAt:),並且定義cell採用我們剛剛設計的adventureCell形式,並將剛剛建立的資料依據列數指定給cell,第0列就取用陣列的第0筆資料,依此類推:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "adventureCell", for: indexPath)
    cell.imageView?.image = UIImage(named: adventureCharacters[indexPath.row])
    cell.textLabel?.text = adventureCharacters[indexPath.row]
    return cell
}


如此一來表格就可以呈現我們想要的形式。

同樣之前實作過的,也可以對不同的section與不同的row指定不同的cell形式:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    switch indexPath.section {
    case 0:
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath)
        return cell
    default:
        switch indexPath.row {
        case 0:
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath)
            return cell
        case 1:
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell3", for: indexPath)
            return cell
        default:
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell4", for: indexPath)
            return cell
        }
    }
}

那我今天偷懶的講解就在這裡告一個段落,好累啊~~
下一回又是重頭戲UITableViewDelegate。
我一天之內能不能看完寫出文章啊......


上一篇
Day 17: 來自深淵-UITableView(II)
下一篇
Day 19: 來自深淵-UITableView(IV)
系列文
Hey! UIKit, 做個朋友吧~30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言