更優雅地使用Static Cell
在項目開發中,經常會用到static cell來實現一些固定的列表界面(如:個人中心等),在static cell被點擊時,如何判斷被點擊的cell是哪一個,有什么好的辦法呢?
如上界面,在storyboard下使用static cell實現起來不過一盞茶的功夫,每個cell對應的操作都不一樣,那么如何確定點擊的是哪一個cell呢?
方法一. 使用indexPath
似乎沒什么好說的,使用indexPath來判斷某一組某一行實在是太簡單,如:
1 if indexPath.section == 1 && indexPath.row == 1 { 2 //我的粉絲 3 } 4 if indexPath.section == 2 && indexPath.row == 1 { 5 //關於我們 6 }
so easy 只需要2個判斷就完成了,但這並不是什么好辦法。如果經常使用static cell的同學很容易就看的出來,如果cell的行數發生了改變(如:添加cell,刪除cell)又或者是cell的位置發生了改變(比如:我的粉絲與我的關注調換位置)這時候就需要重新編寫判斷條件,顯而易見這不是好辦法。
方法二. 使用Tag
為了解決indexPath的不足之處,很多人都會想到使用Tag,每個cell都綁定一個Tag值,這么一來無論是cell的行數發生改變,又或是cell的位置發生改變,都不會影響到判斷條件,如:
這時候添加新的cell只需要給新的cell綁定一個Tag,或者是cell的位置發生改變,並不會影響之前的寫好的判斷條件。
1 guard let cell = tableView.cellForRowAtIndexPath(indexPath) else { return } 2 switch cell.tag { 3 case 101: print("新的好友") 4 case 102: print("新手任務") 5 case 201: print("我的關注") 6 case 202: print("我的粉絲") 7 // ... 8 default: break 9 }
但是,根據101,102,201...這些值無法直接體現出cell對應的內容(或操作),因此可以使用enum改進一下。如:
1 //先定義一個enum 2 enum CellName: Int { 3 case NewFriends = 101 //101:第1組,第01行 4 case NewTask = 102 //102:第1組,第02行 5 case MyFollowing = 201 //201:第2組,第01行 6 case MyFans = 202 //... 7 case Feedback = 301 //... 8 case AboutUs = 302 //... 9 case VersionInfo = 303 //... 10 }
1 guard let cell = tableView.cellForRowAtIndexPath(indexPath) else { return } 2 guard let cellName = CellName(rawValue: cell.tag) else { return } 3 switch cellName { 4 case .NewFriends: //新朋友 5 case .NewTaskL: //新任務 6 case .MyFollowing: //我的關注 7 case .MyFans: //我的粉絲 8 case .Feedback: //意見反饋 9 case .AboutUs: //關於我們 10 case .VersionInfo: //版本信息 11 }
這樣看起來似乎還不錯,但還是稍微有點不足,如果這時候需要在新的好友與新手任務中間插入一行新手禮包,這時候cell的Tag值應該設置為多少呢?當然,只要是不重復的,隨便設置一個Tag=103或者Tag=999都是可以的。但是這時候看起來就會些不協調了,如:
1 enum CellName: Int { 2 case NewFriends = 101 //101:第1組,第01行 3 case NovicePacks = 999 //999:第9組,第99行(但這竟然是第1組第2行) 4 case NewTask = 102 //102:第1組,第02行(但這竟然是第3行) 5 case MyFollowing = 201 //... 6 case MyFans = 202 //... 7 case Feedback = 301 //... 8 case AboutUs = 302 //... 9 case VersionInfo = 303 //... 10 }
這樣雖然也是可以的,也並沒有影響之前的判斷,使用enum之后一樣顯得很友好,但是,如果cell的位置經常改變,產品經理腦子一熱就要求添加一行新的cell,腦子一冷又要求刪掉某一行cell,如此反復之后,cell的Tag就會毫無順序可言,並不好維護。
筆者雖不是處女座,但也無法接受這樣的事情。
方法三. 自定義一個標識(推薦使用,筆者最喜歡的方法)
為了解決Tag反復修改之后變得無序的問題,反正遲早會變得無序,索性一開始就不考慮順序問題。
筆者想到的辦法是,給cell擴展一個字段(叫:actionIdentifier)用於表示當前cell所代表的內容(或操作),且為了能在Storyboard中設置該值,因此加上@IBInspectable修飾,如:
1 private var actionIdentifierKey: Void? 2 3 public extension UITableViewCell { 4 5 @IBInspectable var actionIdentifier: String { 6 get { 7 return objc_getAssociatedObject(self, &actionIdentifierKey) as? String ?? "" 8 } 9 set { 10 objc_setAssociatedObject(self, &actionIdentifierKey, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC) 11 } 12 } 13 14 }
這時候就可以在storyboard中這樣操作,把Action identifier值設置為enum的值,如:
代碼操作跟方法二幾乎無異,如:
1 //這里Int改成String 2 enum ActionIdentifier: String { 3 case NewFriends 4 case NewTask 5 case MyFollowing 6 case MyFans 7 case Feedback 8 case AboutUs 9 case VersionInfo 10 }
1 guard let cell = tableView.cellForRowAtIndexPath(indexPath) else { return } 2 guard let action = ActionIdentifier(rawValue: cell.actionIdentifier) else { return } 3 switch action { 4 case .NewFriends: 5 case .NewTask: 6 //... 7 }
這時候看着就順心多了...
注意:文章中的代碼段均是臨時手寫的,直接copy的話,不一定能編譯通過。
原文鏈接:http://www.jianshu.com/p/3e5ac0e8d43e
著作權歸作者所有,轉載請聯系作者獲得授權,並標注“簡書作者”。
