UITableView 的數(shù)據(jù)顯示主要牽扯到的就是一個(gè)數(shù)據(jù)源方法的使用。
基本思路是:
- 數(shù)據(jù)源的設(shè)置
- 數(shù)據(jù)源方法的實(shí)現(xiàn)
- tableView 對數(shù)據(jù)源的三次詢問
3.1 tableView 有多少組
3.2 tableView 每組有多少行
3.3 tableView 每行顯示什么內(nèi)容
//******************* 這三個(gè)方法是 tableView 顯示數(shù)據(jù)的基本方法蟋字,實(shí)現(xiàn)這三個(gè)方法就可以顯示 tableView 的內(nèi)容 ************************
@available(iOS 2.0, *) // iOS 2.O 開始使用
// tableView 有多少行
public func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
// Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:
// 行顯示的時(shí)候呛占,通過設(shè)置 cell 的重用標(biāo)識符挪拟,和調(diào)用 dequeueReusableCellWithIdentifier 方法來確認(rèn)是否有可重用的 cell歧斟,嘗試去重用 cell肴茄,
// Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)
@available(iOS 2.0, *)
// 每一行 cell 顯示什么內(nèi)容
public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
@available(iOS 2.0, *)
// tableView 有多少組 ( 這個(gè)方法是可選的 默認(rèn)的實(shí)現(xiàn)返回時(shí) 1 晌畅,不實(shí)現(xiàn)這個(gè)數(shù)據(jù)源方法,tableView 就顯示一組數(shù)據(jù))
optional public func numberOfSectionsInTableView(tableView: UITableView) -> Int // Default is 1 if not implemented
1独郎、tableView 數(shù)據(jù)顯示的基本設(shè)置
簡單數(shù)據(jù)展示的實(shí)例
只是展示了一個(gè)單行的文本數(shù)據(jù)
//
// ViewController.swift
// UITableViewTest
//
// Created by 肖卓鴻 on 16/6/2.
// Copyright ? 2016年 肖卓鴻. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
var tableView: UITableView?
override func viewDidLoad() {
super.viewDidLoad()
tableView = UITableView()
// 1. 設(shè)置數(shù)據(jù)源代理
tableView?.dataSource = self
view.addSubview(tableView!)
}
// 2. 這里進(jìn)行 tableView 的 frame 設(shè)置主要是屏幕的適配
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
tableView?.frame = view.frame
}
}
// 實(shí)現(xiàn)數(shù)據(jù)源
// MARK: - UITableViewDataSource
/*
使用擴(kuò)展來實(shí)現(xiàn)數(shù)據(jù)源踩麦,這樣會(huì)使代碼結(jié)構(gòu)看起來更加清晰枚赡。
*/
extension ViewController : UITableViewDataSource {
// 3.1 tableView 有幾組
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
// 3.2 tableView 每組有幾行
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
// 3.3 tableView 每行顯示什么內(nèi)容
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// 創(chuàng)建 cell (cell 沒有使用重用, 此處只是為了展示基本使用)
let cell = UITableViewCell()
// cell 文本數(shù)據(jù)的顯示內(nèi)容設(shè)置
cell.textLabel?.text = "\(indexPath.section)組" + "-" + "\(indexPath.row)行"
return cell
}
}
效果圖:
數(shù)據(jù)源方法調(diào)用的追蹤
在三個(gè)數(shù)據(jù)源方法中添加
print(#function)
numberOfSectionsInTableView
tableView(_:numberOfRowsInSection:)
tableView(_:numberOfRowsInSection:)
numberOfSectionsInTableView
tableView(_:numberOfRowsInSection:)
tableView(_:numberOfRowsInSection:)
numberOfSectionsInTableView
tableView(_:numberOfRowsInSection:)
tableView(_:numberOfRowsInSection:)
numberOfSectionsInTableView
tableView(_:numberOfRowsInSection:)
tableView(_:numberOfRowsInSection:)
tableView(_:cellForRowAtIndexPath:)
tableView(_:cellForRowAtIndexPath:)
tableView(_:cellForRowAtIndexPath:)
tableView(_:cellForRowAtIndexPath:)
tableView(_:cellForRowAtIndexPath:)
tableView(_:cellForRowAtIndexPath:)
tableView(_:cellForRowAtIndexPath:)
tableView(_:cellForRowAtIndexPath:)
tableView(_:cellForRowAtIndexPath:)
tableView(_:cellForRowAtIndexPath:)
- 方法的調(diào)用順序是
numberOfSectionsInTableView
tableView(:numberOfRowsInSection:)
tableView(:cellForRowAtIndexPath:)
2氓癌、cell 視圖的重用
為了提高 tableView 的性能,我們對 cell 進(jìn)行重用贫橙。
使用重用之后贪婉,第一次加載 tableView 的時(shí)候就只會(huì)創(chuàng)建界面可以顯示的幾個(gè) cell,當(dāng)滾動(dòng) tableView 的時(shí)候卢肃,會(huì)從緩存池中獲取 cell 不會(huì)創(chuàng)建 cell 疲迂。當(dāng) cell 消失的時(shí)候?qū)?cell 放入緩存池中。
在上面的數(shù)據(jù)源方法中返回 10000
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100000
}
這樣就可以感覺到明顯的卡頓莫湘。而且內(nèi)存也會(huì)暴漲尤蒿。(在 cell 上設(shè)置圖片后效果會(huì)比較明顯)
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// 創(chuàng)建 cell (cell 沒有使用重用, 此處只是為了展示基本使用)
let cell = UITableViewCell()
print(#function)
return cell
}
會(huì)打印 100000 次
使用重用后,界面可以顯示幾個(gè) cell 就打印幾次
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// 老程序員會(huì)這么寫 cell 的重用
var cell = tableView.dequeueReusableCellWithIdentifier("cell")
if cell == nil {
cell = UITableViewCell(style: .Default, reuseIdentifier: "cell")
}
print(#function)
return cell!
}
相比之下性能會(huì)高很多
上面是老式的 cell 的重用寫法
cell 重用的使用步驟
- 注冊 cell
- 數(shù)據(jù)源方法中獲取 cell
- 設(shè)置 cell 的數(shù)據(jù)后 在數(shù)據(jù)源方法中返回 cell
cell 的注冊:
// cell 的 nib 方式注冊幅垮,
public func registerNib(nib: UINib?, forCellReuseIdentifier identifier: String)
// cell 的 class 方式注冊
public func registerClass(cellClass: AnyClass?, forCellReuseIdentifier identifier: String)
// header 和 footer nib 方式注冊
public func registerNib(nib: UINib?, forHeaderFooterViewReuseIdentifier identifier: String)
// header 和 footer class 方式注冊
public func registerClass(aClass: AnyClass?, forHeaderFooterViewReuseIdentifier identifier: String)
// 注冊代碼
tableView.registerClass(UITableViewCell.classForCoder(), forCellReuseIdentifier: UITableViewCell.identifier)
tableView.registerNib(UITableViewCell.nib, forCellReuseIdentifier: UITableViewCell.identifier)
// UITableViewCell.nib 和 UITableViewCell.identifier 的說明
import UIKit
extension UITableViewCell {
/*!
cell 重用標(biāo)識符 (標(biāo)識符默認(rèn)就是 class 的字符串)
*/
class var identifier:String {
return "\(self.classForCoder())"
}
/*!
cell 的 nib 文件
*/
class var nib:UINib {
return UINib(nibName: "\(self.classForCoder())", bundle: nil)
}
}
使用 UITableViewCell.nib 和 UITableViewCell.identifier 這種方式可以避免直接寫字符串容易寫錯(cuò)的麻煩
注意點(diǎn): 使用 nib 方式的時(shí)候腰池,xib 的文件名稱和 視圖類的類名一定要相同。
緩存池中 cell 的獲取
public func dequeueReusableCellWithIdentifier(identifier: String) -> UITableViewCell? // Used by the delegate to acquire an already allocated cell, in lieu of allocating a new one.
// 使用這個(gè)方法 cell 必須是注冊的(這是和上面方法的最大區(qū)別)
public func dequeueReusableCellWithIdentifier(identifier: String, forIndexPath indexPath: NSIndexPath) -> UITableViewCell
// cell 從緩存池中獲取的代碼
// 不進(jìn)行注冊忙芒,就使用舊的寫法就可以了
let cell = tableView.dequeueReusableCellWithIdentifier(UITableViewCell.identifier)
// 使用這個(gè)方法 cell 必須提前注冊
let cell = tableView.dequeueReusableCellWithIdentifier(UITableViewCell.identifier, forIndexPath: indexPath)
// cell 數(shù)據(jù)的設(shè)置 和 cell 返回
cell?.textLabel?.text = "hello world"
return cell!