[Android開發學iOS系列] TableView展現一個list

来源:https://www.cnblogs.com/mengdd/archive/2022/11/22/iOS-tableview-basics.html
-Advertisement-
Play Games

TableView 基礎 本文講講TableView的基本使用. 順便介紹一下delegation. TableView用來做什麼 TableView用來展示一個很長的list. 和Android中的RecyclerView不同, iOS中的TableView只能是豎直方向的list. 如何寫一個最 ...


TableView 基礎

本文講講TableView的基本使用.
順便介紹一下delegation.

TableView用來做什麼

TableView用來展示一個很長的list.
和Android中的RecyclerView不同, iOS中的TableView只能是豎直方向的list.

如何寫一個最簡單的TableView

一個最簡單的TableViewController看起來像這樣:

class ViewController: UITableViewController {
    var data: [String] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        // loadData()
        print(data)
    }

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath)
        cell.textLabel?.text = data[indexPath.row]
        return cell
    }
}

這裡data是想展示的數據類型, 可以hardcode一些數據.

這麼簡單是因為這個ViewController繼承了UITableViewController, 並且cell的部分使用了storyboard.

這裡需要用dequeueReusableCell方法, 是為了cell的復用, 因為list內容很多的時候cell view是可以迴圈使用的. (很像Android里的RecyclerView).

UITableViewController的簽名是這樣:

open class UITableViewController : UIViewController, UITableViewDelegate, UITableViewDataSource {

它為我們做了以下三件事:

  • 設置view為一個UITableView.
  • 設置delegate=self.
  • 設置dataSource=self.

這種方式的局限性在於第一點, 它的根view是一個TableView, 如果我們的需求比較複雜, 不僅僅是一個demo, 那麼可能需要組合View.

拆解版TableView

我們也可以直接繼承UIViewController類, 然後自己動手做上面的幾條設置.

Delegate & DataSource

TableView有兩個重要的方面需要關註:

  • UITableViewDelegate: 管理和用戶的交互, 比如選擇, 滑動手勢等. 沒有必須要實現的方法.
  • UITableViewDataSource: 提供和管理數據, 包括了數據對應的cell或者header. 有兩個必須要實現的方法(如上面的代碼例子所示).

繼承UIViewController

繼承UIViewController而不是UITableViewController之後, 需要自己寫一個tableView並加在view里.
再分別實現UITableViewDelegateUITableViewDataSource, 這裡寫在extension里, 拆分完之後set給tableView:

tableView.delegate = self
tableView.dataSource = self

整體改造後代碼如下:

class ViewController: UIViewController {
    var data: [String] = ["Hello", "World"]

    private let tableView = UITableView()

    override func loadView() {
        view = UIView()
        view.addSubview(tableView)
        tableView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            tableView.topAnchor.constraint(equalTo: view.topAnchor),
            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        ])
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(MyCell.self, forCellReuseIdentifier: "MyCell")
        tableView.delegate = self
        tableView.dataSource = self
    }
}

extension ViewController: UITableViewDelegate {}

extension ViewController: UITableViewDataSource {
    func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int {
        data.count
    }

    func tableView(_: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as? MyCell {
            cell.configure(with: data[indexPath.row])
            return cell
        }
        return UITableViewCell()
    }
}

自己的Cell class

這裡Cell也改用代碼類, 寫一個這樣的類:

class MyCell: UITableViewCell {
    private let label = UILabel()
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        contentView.addSubview(label)
        label.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            label.topAnchor.constraint(equalTo: contentView.topAnchor),
            label.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),
            label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
            label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
        ])
    }

    @available(*, unavailable)
    required init?(coder _: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func configure(with data: String) {
        label.text = data
    }
}

註意tableView註冊這個Cell類型:

override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(MyCell.self, forCellReuseIdentifier: "MyCell")
}

補充知識: Delegation

上面的方法初看可能會非常怪. 這裡還涉及到了一個知識點是iOS中的delegate.
它存在的意義是為了拓展本身類的功能.

Apple自己的很多API就用了delegate protocol, 比如UIApplicationDelegate, UITableViewDelegate.
如果我們想自己定義一個:

protocol MyTypeDelegate: AnyObject {
    func myType(_ myType: MyType,
                      shouldDoSomething argumentString: String) -> Bool

    func myType(_ myType: MyType,
                      didAbortWithError error: Error)

    func myTypeDidFinish(_ myType: MyType)
}

class MyType {
    weak var delegate: MyTypeDelegate?
}

定義delegation的幾個原則:

  • 方法名以被代理的類型開頭.
  • 方法的第一個參數是被代理的對象.

References

作者: 聖騎士Wind
出處: 博客園: 聖騎士Wind
Github: https://github.com/mengdd
微信公眾號: 聖騎士Wind
微信公眾號: 聖騎士Wind
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • (文章目錄) 一、調度演算法的原理和分類 1.進程調度簡介 進程調度的研究是整個操作系統理論的核心,在多進程的操作系統中,進程調度是一個全局性的、關鍵性的問題,它對系統的總體設計、系統的實現、功能設置以及各方面的性能都有著決定性的影響。進程運行需要各種各樣的系統資源,如記憶體、文件、印表機和最寶貴的CP ...
  • GreatSQL社區原創內容未經授權不得隨意使用,轉載請聯繫小編並註明來源。 GreatSQL是MySQL的國產分支版本,使用上與MySQL一致。 作者:nw MySQL Hash Join前世今生 因工作需要,對MySQL Hash Join的內部實現做了一些探索和實踐,對這個由8.0.18開始引 ...
  • 前端做數據分頁,至少需要傳給後端的關鍵數據: 當前頁碼:pageNum(需要查第幾頁的數據,必須前端提供) 每頁顯示數據條數:limit 或 pageSize(可前端傳,可後端自定義) 前端需要的數據,即後端需要查的數據:(可定義 PageHelper 封裝數據) int count:總記錄數 (直 ...
  • 首發微信公眾號:SQL資料庫運維 原文鏈接:https://mp.weixin.qq.com/s?__biz=MzI1NTQyNzg3MQ==&mid=2247485212&idx=1&sn=450e9e94fa709b5eeff0de371c62072b&chksm=ea37536cdd40da7 ...
  • 摘要:為了持續打造核心競爭力,英克康健聯合華為雲,基於雲資料庫RDS for PostgreSQL全新打造了一個高性能、大容量、高可用的SaaS醫葯管理系統,助力萬千藥企業務邁上新臺階。 本文分享自華為雲社區《雲時代下,醫葯行業管理居然這麼簡單》,作者:GaussDB 資料庫 。 乘借數字化東風,醫 ...
  • 在mysql中,hint指的是“查詢優化提示”,會提示優化器按照一定的方式來生成執行計划進行優化,讓用戶的sql語句更具靈活性;Hint可基於表的連接順序、方法、訪問路徑、並行度等規則對DML(數據操縱語言,Data Manipulation Language)語句產生作用。 我們在操作表、欄位或索 ...
  • 簡述 SQL Server 是一個值得信賴的老牌資料庫系統,自從 1988 年由 Microsoft、Sybase 和 Ashton-Tate 三家公司共同推出之後就一直不斷迭代更新。而如今我們提到 SQL Server 通常是指 Microsoft 從 SQL Server 2000 之後的版本。 ...
  • 我是風箏,公眾號「古時的風箏」,專註於 Java技術 及周邊生態。 文章會收錄在 JavaNewBee 中,更有 Java 後端知識圖譜,從小白到大牛要走的路都在裡面。 有朋友聊到他們的系統中要接入全文檢索,這讓我想起了很久以前為一個很古老的項目添加搜索功能的事兒。 一提到全文檢索,我們首先就會想到 ...
一周排行
    -Advertisement-
    Play Games
  • 簡介 本文的初衷是希望幫助那些有其它平臺視覺演算法開發經驗的人能快速轉入Halcon平臺下,通過文中的示例開發者能快速瞭解一個Halcon項目開發的基本步驟,讓開發者能把精力完全集中到演算法的開發上面。 首先,你需要安裝Halcon,HALCON 18.11.0.1的安裝包會放在文章末尾。安裝包分開發和 ...
  • 本文是對Datawhale的動手學數據分析課程的學習總結,記錄了整體的學習過程、答案以及個人感想,代碼較為詳細。 ...
  • JZ7重建二叉樹 描述 給定節點數為 n 的二叉樹的前序遍歷和中序遍歷結果,請重建出該二叉樹並返回它的頭結點。 例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6} 提示: 1.vin.length == pre.length 2.pre 和 vin ...
  • 我們都知道在Java編程中多線程的同步使用synchronized關鍵字來標識,那麼這個關鍵字在JVM底層到底是如何實現的呢。 我們先來思考一下如果我們自己實現的一個鎖該怎麼做呢: 首先肯定要有個標記記錄對象是否已經上鎖,執行同步代碼之前判斷這個標誌,如果對象已經上鎖線程就阻塞等待鎖的釋放。 其次要 ...
  • 目錄 一.OpenGL 色階 1.Windows OpenGL ES 版本 2.Windows OpenGL 版本 二.OpenGL 色階 GLSL Shader 三.猜你喜歡 零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 基礎 零基礎 Ope ...
  • 1. 查看Linux伺服器版本信息 # cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core) 2. 禪道開源版安裝包下載 wget http://dl.cnezsoft.com/zentao/9.8.2/ZenTaoPMS.9.8. ...
  • Spring 框架可以為 Java 應用程式開發提供全面的基礎設施支持,它是現在非常流行的 Java 開源框架,對於一個 Java 開發人員來說,熟練掌握 Spring 是必不可少的。 ...
  • 前言 本篇是c++總結的第二篇,關於c++的對象模型,在構造、拷貝虛函數上重點分析,也包含了c++11class的新用法和特性,如有不當,還請指教! c++三大特性 訪問許可權 ​ 在c++中通過public、protected、private三個關鍵字來控製成員變數和成員函數的訪問許可權,它們分別表示 ...
  • 一.小結 1.使用二維數組來存儲表格 2.可以使用以下語法來聲明二維數組變數: 元素類型[ ] [ ]數組變數 3.可以使用以下語法來創建二維數組變數: new 元素類型 [行的個數][列的個數] 4.使用下麵的語法表示二維數組中的每個元素: 數組變數[行下標][列的個數] 5.可使用數組初始化語法 ...
  • typimg是一款為typora編輯器提供圖像自定義上傳服務的工具,該工具將在typora中輸入的網路圖片、本地圖片、剪貼板圖片/截圖上傳到博客園,支持在MacOS、Windiws、Linux三個平臺上運行。 ...