為什麼 iOS delegate / data source function 的第一個參數常常是它對應的元件

iOS delegate / data source function 的第一個參數常常是它對應的元件,比方以下例子。

  • scrollViewDidScroll(_:) 的第一個參數是 scroll view。
optional func scrollViewDidScroll(_ scrollView: UIScrollView)
  • tableView(_:didSelectRowAt:) 的第一個參數是 table view。
optional func tableView(
_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath
)
  • tableView(_:cellForRowAt:) 的第一個參數是 table view。
func tableView(
_ tableView: UITableView,
cellForRowAt indexPath: IndexPath
) -> UITableViewCell

為什麼 Apple 習慣將這些 function 的第一個參數設計成 delegate / data source 對應的元件呢 ? 它有許多好處,其中一個在於當有多個元件共用同一個 delegate / data source 時,我們可從參數區分判斷做不同的事。

以下我們以奧運 App 為例,如下圖所示,畫面上有 2 個 collection view,分別顯示奧運運動 icon 的小圖和吉祥物的大圖。

2 個 collection view 的 data source 都是 OlympicViewController,因此我們必須在 function collectionView(_:numberOfItemsInSection:) 和 collectionView(_:cellForItemAt:) 判斷對應的 collection view 才能顯示正確的內容。

為了區分不同的 collection view,我們先連接 outlet mascotCollectionView & gameCollectionView。


class OlympicViewController: UIViewController {

@IBOutlet weak var mascotCollectionView: UICollectionView!
@IBOutlet weak var gameCollectionView: UICollectionView!

之後在 data source function 將參數 collectionView 和 outlet 比對,即可決定回傳的 cell 數量和內容。

extension OlympicViewController: UICollectionViewDataSource {

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == mascotCollectionView {
return mascots.count
} else {
return games.count
}
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == mascotCollectionView {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "\(MascotCollectionViewCell.self)", for: indexPath) as! MascotCollectionViewCell
cell.imageView.image = UIImage(named: "\(mascots[indexPath.item])")
return cell
} else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "\(GameCollectionViewCell.self)", for: indexPath) as! GameCollectionViewCell
cell.imageView.image = UIImage(named: games[indexPath.item])
return cell
}

}
}

--

--

彼得潘的 iOS App Neverland
彼得潘的 Swift iOS App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com