實現 UITableViewCell 側滑操作列表

所有文章已搬遷到個人站點:me.harley-xk.studio,歡迎訪問留言

曾經

我們都知道 UITableView 支持實現側滑操作,一般用來實現刪除一個項目,實現起來也很簡單,只需要實現 UITableView 的三個代理方法

  • 首先告訴UITableView我們需要實現的操作類型,比如返回一個.delete
public func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
    return .delete
}
  • 然后告訴 UITableView 側滑時刪除按鈕上顯示的文字
func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
    return "Delete"
}
  • 最后實現按鈕觸發后執行的操作
public func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    // Do somthing
}

幾個項目下來,我們對這個三部曲早就是滾瓜爛熟了。不過有時候會想,一個簡單的操作按鈕,需要實現三個 Delegate 方法來達到效果,會不會太繁瑣了。。。

更何況還有一件更坑的事情:editingStyleForRowtitleForDeleteConfirmationButton這兩個方法屬于UITableViewDelegate協議,而commit editingStyle這個方法屬于UITableViewDataSource協議。

這意味著,如果你為UITableView實現了通用的DataSource協議,那么要實現側滑操作就不可避免要破壞代碼結構了。。。

另外,側滑支持多項操作的需求越來越旺盛,而此時我們的經典三部曲已經無法勝任工作了。

這時候要么選擇第三方的實現方案,做好隨時被坑的準備;要么,自己去實現一個更大的。。。坑?

iOS 8 之后

估計蘋果的工程師也為自己這個天才的設計折服了吧,于是在 iOS 8 引入了一個新的 API:UITableViewRowAction,先來看一看定義壓壓驚:

@available(iOS 8.0, *)
open class UITableViewRowAction : NSObject, NSCopying {
    
    public convenience init(style: UITableViewRowActionStyle, title: String?, handler: @escaping (UITableViewRowAction, IndexPath) -> Swift.Void)
    
    open var style: UITableViewRowActionStyle { get }

    open var title: String?

    @NSCopying open var backgroundColor: UIColor? // default background color is dependent on style

    @NSCopying open var backgroundEffect: UIVisualEffect?
}

先來看構造器,便利構造器接受三個屬性:styletitlehandler

title這個不用說了,肯定就是按鈕顯示的標題了。

style通過定義可以看到,是一個UITableViewRowActionStyle類型的枚舉值,通過構造器傳入之后便不可更改了,想來是決定操作按鈕的顯示樣式的吧,destructive這個單詞是不是很熟悉?

@available(iOS 8.0, *)
public enum UITableViewRowActionStyle : Int {
    case `default`
    case destructive
    case normal
}

繼續往下看到handler,這是一個閉包,顯然是用來響應按鈕點擊事件的了,終于不用另外實現一個Delegate方法去響應操作事件了么?自從 iOS 4 之后引入了 block,蘋果已經一發不可收拾了,API 改造大軍正在路上。。。

class 定義里面還有兩個屬性:

首先看到backgroundColor,字面意思很好理解,就是背景顏色了,后面注釋了一行小字:default background color is dependent on style

這證實了我們的猜想:style屬性決定了按鈕的樣式,也就是背景顏色,當然,我們也可以通過backgroundColor自己另外指定背景色。

最后一個屬性是backgroundEffect,是UIVisualEffect類型的。UIVisualEffect?!這是啥?有經驗的同學都知道,這是 iOS 7 之后引入的毛玻璃特效啊,不過研究了半天發現并沒有卵用??。也可能是我打開的方式不對?有知道的同學可以指點下。。。

實踐

好了,看完了類定義,趕緊來看看怎么使用吧。先看一下UITableViewDelegate的定義,關于UITableViewRowAction只定義了一個方法:

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?

終于決定拋棄三部曲了么??,返回值是個數組,這是支持多個操作項的節奏啊,廢話少說上代碼:

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {
    let defaultAction = UITableViewRowAction(style: .default, title: "Default")     { (action, indexPath) in
        self.alertTitle("Default action at \(indexPath)")
    }
    let normalAction = UITableViewRowAction(style: .normal, title: "Normal") { (action, indexPath) in
        self.alertTitle("Normal action at \(indexPath)")
    }
    let destructiveAction = UITableViewRowAction(style: .destructive, title: "Delete") { (action, indexPath) in
        self.alertTitle("Delete action at \(indexPath)")
    }
    return [defaultAction, normalAction, destructiveAction]
}

func alertTitle(_ title: String) {
    let alert = UIAlertController(title: title, message: nil, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
    present(alert, animated: true)
}

這里定義了三個UITableViewRowAction,分別對應不同的style,運行之后可以發現,defaultdestructive默認都是紅色,normal默認是灰色。這里只是簡單定義了一個alertTitle方法用來響應點擊反饋,實際項目中需要替換成特定的業務邏輯。

結語

至此終于水完了UITableViewRowAction相關的內容,雖然這是個 iOS 8 就出來的特性了,不過最近才被我注意到,而且還沒有把backgroundEffect屬性的特性摸清,實在是慚愧。

好消息是現在大多數 App 都是至少支持 iOS 8 + 了吧?可以再也不用寫繁瑣的三部曲了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • WebSocket-Swift Starscream的使用 WebSocket 是 HTML5 一種新的協議。它實...
    香橙柚子閱讀 24,124評論 8 183
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,257評論 4 61
  • 大提琴里流淌出的旋律,像一個游離而落魄的詩人,他滿身疲倦的淌過小河,躍過大山,瞇著小眼抬頭的那一瞬間,他抓住了余暉...
    草根夢途閱讀 229評論 0 0
  • 從前從前,有一只不知名的鳥,聲音比黃鸝鳥還要好聽,但極其丑陋,它沒有其他的同伴,從它來到這個世界,睜開眼的那一刻起...
    鹿知森閱讀 1,466評論 0 0
  • 煙雨留城, 瀟瀟雨墨研開了天空, 畫下了你
    舊城丶雨憶閱讀 210評論 0 0