更優雅地使用Static Cell

okra 8年前發布 | 4K 次閱讀 iOS開發 移動開發 Storyboard

在項目開發中,經常會用到static cell來實現一些固定的列表界面(如:個人中心等),在static cell被點擊時,如何判斷被點擊的cell是哪一個,有什么好的辦法呢?

個人中心

如上界面,在storyboard下使用static cell實現起來不過一盞茶的功夫,每個cell對應的操作都不一樣,那么如何確定點擊的是哪一個cell呢?

方法一. 使用indexPath

似乎沒什么好說的,使用indexPath來判斷某一組某一行實在是太簡單,如:

if indexPath.section == 1 && indexPath.row == 1 {
     //我的粉絲
}
if indexPath.section == 2 && indexPath.row == 1 {
    //關于我們
}

so easy 只需要2個判斷就完成了,但這并不是什么好辦法。如果經常使用static cell的同學很容易就看的出來,如果cell的行數發生了改變(如:添加cell,刪除cell)又或者是cell的位置發生了改變(比如: 我的粉絲 與 我的關注 調換位置)這時候就需要重新編寫判斷條件,顯而易見這不是好辦法。

方法二. 使用Tag

為了解決indexPath的不足之處,很多人都會想到使用Tag,每個cell都綁定一個Tag值,這么一來無論是cell的行數發生改變,又或是cell的位置發生改變,都不會影響到判斷條件,如:

給cell設置Tag值

這時候添加新的cell只需要給新的cell綁定一個Tag,或者是cell的位置發生改變,并不會影響之前的寫好的判斷條件。

guard let cell = tableView.cellForRowAtIndexPath(indexPath) else { return }
  switch cell.tag {
    case 101:   print("新的好友")
    case 102:   print("新手任務")
    case 201:   print("我的關注")
    case 202:   print("我的粉絲")
    // ...
    default:    break
}

但是,根據101,102,201...這些值無法直接體現出cell對應的內容(或操作),因此可以使用 enum 改進一下。如:

//先定義一個enum
enum CellName: Int {
    case NewFriends     = 101  //101:第1組,第01行
    case NewTask        = 102  //102:第1組,第02行
    case MyFollowing    = 201  //201:第2組,第01行
    case MyFans         = 202  //...
    case Feedback       = 301  //...
    case AboutUs        = 302  //...
    case VersionInfo    = 303  //...
}
guard let cell = tableView.cellForRowAtIndexPath(indexPath) else { return }
guard let cellName = CellName(rawValue: cell.tag) else { return }
switch cellName {
  case .NewFriends:       //新朋友
  case .NewTaskL:         //新任務
  case .MyFollowing:      //我的關注
  case .MyFans:           //我的粉絲
  case .Feedback:         //意見反饋
  case .AboutUs:          //關于我們
  case .VersionInfo:      //版本信息
}

這樣看起來似乎還不錯,但還是稍微有點不足,如果這時候需要在 新的好友 與 新手任務 中間插入一行 新手禮包 ,這時候cell的Tag值應該設置為多少呢?當然,只要是不重復的,隨便設置一個 Tag=103 或者 Tag=999 都是可以的。但是這時候看起來就會些不協調了,如:

enum CellName: Int {
    case NewFriends     = 101  //101:第1組,第01行
    case NovicePacks    = 999  //999:第9組,第99行(但這竟然是第1組第2行)
    case NewTask        = 102  //102:第1組,第02行(但這竟然是第3行)
    case MyFollowing    = 201  //...
    case MyFans         = 202  //...
    case Feedback       = 301  //...
    case AboutUs        = 302  //...
    case VersionInfo    = 303  //...
}

這樣雖然也是可以的,也并沒有影響之前的判斷,使用 enum 之后一樣顯得很友好, 但是 ,如果cell的位置經常改變,產品經理腦子一熱就要求添加一行新的cell,腦子一冷又要求刪掉某一行cell,如此反復之后,cell的Tag就會毫無順序可言,并不好維護。

筆者雖不是處女座,但也無法接受這樣的事情。

方法三. 自定義一個標識(推薦使用,筆者最喜歡的方法)

為了解決Tag反復修改之后變得無序的問題,反正遲早會變得無序,索性一開始就不考慮順序問題。

筆者想到的辦法是,給cell擴展一個字段(叫: actionIdentifier )用于表示當前cell所代表的內容(或操作),且為了能在Storyboard中設置該值,因此加上 @IBInspectable 修飾,如:

private var actionIdentifierKey: Void?

public extension UITableViewCell {

    @IBInspectable var actionIdentifier: String {
        get {
            return objc_getAssociatedObject(self, &actionIdentifierKey) as? String ?? ""
        }
        set {
            objc_setAssociatedObject(self, &actionIdentifierKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
        }
    }

}

這時候就可以在storyboard中這樣操作,把Action identifier值設置為enum的值,如:

設置ActionIdentifier值

代碼操作跟方法二幾乎無異,如:

//這里Int改成String
enum ActionIdentifier: String {
    case NewFriends
    case NewTask
    case MyFollowing
    case MyFans
    case Feedback
    case AboutUs
    case VersionInfo
}
guard let cell = tableView.cellForRowAtIndexPath(indexPath) else { return }
guard let action = ActionIdentifier(rawValue: cell.actionIdentifier) else { return }
switch action {
  case .NewFriends:
  case .NewTask:
  //...
}

這時候看著就順心多了...

注意:文章中的代碼段均是臨時手寫的,直接copy的話,不一定能編譯通過。

 

 

來自:http://www.jianshu.com/p/3e5ac0e8d43e

 

 本文由用戶 okra 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!