UITableView 協議方法中更好的 switch 使用方案

Cove

UITableView 幾乎是每個原生 App 都會使用到的控件,因此你必定對 UITableViewDataSourceUITableViewDelegate 中的代理方法很熟悉。在一些代理方法中有時候咱們須要對不一樣的 section、row 進行分開處理,此時咱們都會使用 switch 來應對。因此接下來將會介紹一種更好的 switch 使用方案。編程

常規處理

大多數狀況下,咱們使用的 switch 方案都是相似下面的硬編碼方式:app

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    switch indexPath.section {
        case 0: // Dequeue a cell for section 0
        case 1: // Dequeue a cell for section 1
        // And so on...
        default: fatalError("Unhandled section \(indexPath.section)")
    }
}

上訴代碼在功能上並無什麼權限,可是這種硬編碼方式對後期的代碼維護帶來的隱性成本。其實一個好的編程習慣就是最大限度的避免硬編碼,不管是 switch 仍是設置 view 的 tag 的時候都應該採用更爲「優雅」的方式。函數

更好的處理方式

對於硬編碼的優雅的替換方案大多數狀況下都是使用 enum 方式,在枚舉類型中咱們可使用更具識別性的詞語。這樣不只能一眼識別含義,並且在後期修改的過程當中也不用滿世界找硬編碼的數字生怕有遺漏。ui

接下來直接上碼:編碼

protocol ReusableViewEnum {}

extension ReusableViewEnum where Self: RawRepresentable, Self.RawValue == Int {
    static var all: [Self] {
        var index = 0
        var allItems = [Self]()
        while let item = Self(rawValue: index) {
            allItems.append(item)
            index += 1
        }
        return allItems
    }

    static func build(with value: Int) -> Self {
        guard let row = Self(rawValue: value) else {
            fatalError("Unimplemented value: \(value)")
        }
        return row
    }
}

// ---------------------
// EXAMPLE USAGE CODE:

// You only have to define the enum
fileprivate enum ProfileSections: Int, ReusableViewEnum {
    case picture = 0
    case name
    case email
    case password
}

// And use it in your code:
func numberOfSections(in tableView: UITableView) -> Int {
    return ProfileSections.all.count
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    switch ProfileSection.build(with: section) {
        case .picture   : return 1
        case .name      : return 1  
        case .email     : return 1 
        case .password  : return 1 
    }
}   

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    switch ProfileSection.build(with: indexPath.section) {
        case .picture   : // Dequeue profile picture section
        case .name      : // Dequeue name section
        case .email     : // Dequeue email section
        case .password  : // Dequeue password section
    }
}

首先,咱們什麼了 ReusableViewEnum 協議並對其進行了拓展。在拓展中咱們添加了一個計算屬性 all, 用於表示遵循該協議而且 rawValue 爲 Int的枚舉類型的全部取值。另外增長了用 Int 來構建枚舉類型的函數 buildspa

在使用實例中咱們定義了枚舉類型 ProfileSections,並在 UITableView 的代理方法中實現了上面 ReusableViewEnum 協議的應用。應用後的 switch 方案代碼風格更爲有效,後期維護效率也明顯優於以前的硬編碼方式。代理

相關文章
相關標籤/搜索