Swift的枚举里面可以包含方法,这件事让我感到很困惑。这疯狂的模式是看着是那么优美。我也曾经有这样想过,在枚举里面可以通过映射数字来详细描述里面包含的值。就是这样!不过,这周开发用到了几个简单的TableViews和CollectionViews,让我深深爱上了用复杂的Swift枚举来开发的这种简单方式。我想在这里跟大家分享一下我亲身尝试过的模式,同时我也希望听到你们的意见。
One of the things that puzzled me about Swift when it came out was that you could put functions in an enum! That seemed like a pretty crazy pattern. I’m used to thinking of enums exactly as that – enums where I can specify values that are mapped into number. That’s it!
However, as I’ve been working on a few simple Swift TableViews and CollectionViews this week, I fell in love with how simple the complex Swift enum can make things. I’d like to share the pattern I’ve been experimenting with, and I’d love to hear what you think about it in the comments.
下面我将会开发一个关于小黄人(出自卑鄙的我)的非常简单的表格视图。每一个单元格都会有图片和对应小黄人的名字:
I’m going to build a very simple table view of Minions (from Despicable Me). Each cell in the table view will only have the image and name of the relevant minion:
然后我用尽可能多的数据完成了下面这个枚举:
I built my enum as more of a data object:
enum MinionIndex: Int {
case DAVE, BOB, JERRY, JORGE, KEVIN, MARK, PHIL, STUART, TIM
static let minionNames = [
DAVE : "Dave",
BOB : "Bob",
JERRY : "Jerry",
JORGE : "Jorge",
KEVIN : "Kevin",
MARK : "Mark",
PHIL : "Phil",
STUART : "Stuart",
TIM : "Tim"
]
func minionName() -> String {
if let minionName = MinionIndex.minionNames[self] {
return minionName
} else {
return "Minion"
}
}
func minionImage() -> UIImage {
return UIImage(named: "Minion\(minionName())")
}
}
除了将每一个小黄人都映射到一个整型外,还用一个静态字典将每一个小黄人的名字和他们的索引映射到一起,还有一个从静态字典获取小黄人名字的方法,以及一个返回小黄人图片的方法。
这样,我的tableView:cellForRowAtIndexPath:这个方法就变得非常精简:
Besides just mapping a minion to an int, there is a static dictionary that maps the minion’s index to a minion’s name, a function that gets the minion’s name from that static dictionary, and a function that returns the minion’s image.
This makes my tableView:cellForRowAtIndexPath: method very simple:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier(minionCellIdentifier) as UITableViewCell
if let minionIndex = MinionIndex.fromRaw(indexPath.row) {
cell.textLabel.text = minionIndex.minionName()
cell.imageView.image = minionIndex.minionImage()
}
return cell
}
留心这些数据,索引、名字、小黄人图像是如何在枚举里面关联起来的。在使用Objective-C的时候,我会声明一个枚举、一个包含小黄人名字的数组,还很可能会有一个通过小黄人名字获取对应图像的方法,还有更糟的,我可能会用一大串Switch语句使得tableView:cellForRowAtIndexPath:变得非常臃肿。我的同事@louielouie 称这样的开发模式为“反开关语句模式”。
Notice how the data – index, name, image of the minion – stays together in the enum. In Objective-C, I would have had an enum, an array of minion names, and likely a function to convert minion names into an image, or worse – I could have used Switch statements to make a much longer tableView:cellForRowAtIndexPath: method. In fact, my coworker@louielouie actually calls this the “anti-switch-statement pattern”.
Overall, I’ve been enjoying using this pattern for my new iOS 8 Swift TableViews.
Let me know what you think!
You can view the full source code on Github here.