Swift中枚举的使用方法简单介绍

枚举我们大家都不太陌生了,我们在C或者OC中经常使用到,在这里简单记录下Swift中枚举的使用方法.

枚举的定义

“在 Swift 中,枚举类型是一等(first-class)类型。它们采用了很多在传统上只被类(class)所支持的特性,例如计算型属性(computed properties),用于提供枚举值的附加信息,实例方法(instance methods),用于提供和枚举值相关联的功能。枚举也可以定义构造函数(initializers)来提供一个初始值;可以在原始实现的基础上扩展它们的功能;还可以遵守协议(protocols)来提供标准的功能。”

枚举的语法

使用enum关键词来创建枚举并且把它们的整个定义放在一对大括号内:
下面是用枚举表示指南针四个方向的例子:

enum CompassPoint {
    case North
    case South
    case East
    case West
}

枚举中定义的值(如 North,South,East和West)是这个枚举的成员值(或成员)。使用case关键字来定义一个新的枚举成员值。

注意:

与 C 和 Objective-C 不同,Swift 的枚举成员在被创建时不会被赋予一个默认的整型值。在上面的CompassPoint例子中,North,South,East和West不会被隐式地赋值为0,1,2和3。相反,这些枚举成员本身就是完备的值,这些值的类型是已经明确定义好的CompassPoint类型。多个成员值可以出现在同一行上,用逗号隔开:

enum Planet {
    case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}

每个枚举定义了一个全新的类型。像 Swift 中其他类型一样,它们的名字(例如CompassPoint和Planet)必须以一个大写字母开头。给枚举类型起一个单数名字而不是复数名字,以便于读起来更加容易理解:
可以使用switch语句匹配单个枚举值:

directionToHead = .South
switch directionToHead {
    case .North:
 print("Lots of planets have a north")
    case .South:
        print("Watch out for penguins")
“case .East:
        print("Where the sun rises")
    case .West:
        print("Where the skies are blue")
}
// 输出 "Watch out for penguins”
关联值(Associated Values)

在 Swift 中,我们还可以定义这样的枚举类型,它的每一个枚举项都有一个附加信息,来扩充这个枚举项的信息表示,这又叫做关联值。加入我们有一个枚举类型Shape
来表示形状。这个形状可以是矩形,也可以是圆形,等等。而每种具体的形状又对应了不同的属性,比如矩形有长,宽,圆形有,圆心,半径,等等。那么枚举的关联值就可以帮我们解决这个问题:

enum Shape { case Rectangle(CGRect) case Circle(CGPoint,Int)}

我们看到,每个枚举项的后面,都包含了一对括号,这里面定义了这个枚举项的关联值的类型。对于Rectangle我们使用一个CGRect来表示他的原点和长宽属性。而对于Circle
,我们使用一个包含了CGPointInt类型的元组(Tuple) 来表示这个圆的圆心和半径。
这样我们在初始化枚举类型的时候,我们就可以根据每个枚举项的关联值类型,为它指定附加信息了:

var rect = Shape.Rectangle(CGRectMake(0, 0, 200, 200))var circle = Shape.Circle(CGPointMake(25, 25), 20)
原始值(Raw Values)

“原始值和关联值是不同的。原始值是在定义枚举时被预先填充的值。对于一个特定的枚举成员,它的原始值始终不变。关联值是创建一个基于枚举成员的常量或变量时才设置的值,枚举成员的关联值可以变化。

原始值的隐式赋值(Implicitly Assigned Raw Values)

在使用原始值为整数或者字符串类型的枚举时,不需要显式地为每一个枚举成员设置原始值,Swift 将会自动为你赋值。

例如,当使用整数作为原始值时,隐式赋值的值依次递增1。如果第一个枚举成员没有设置原始值,其原始值将为0。
下面的枚举是对之前Planet这个枚举的一个细化,利用整型的原始值来表示每个行星在太阳系中的顺序:

enum Planet: Int {
    case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
}```
在上面的例子中,Plant.Mercury的显式原始值为1,Planet.Venus的隐式原始值为2,依次类推。
当使用字符串作为枚举类型的原始值时,每个枚举成员的隐式原始值为该枚举成员的名称。
下面的例子是CompassPoint枚举的细化,使用字符串类型的原始值来表示各个方向的名称:

enum CompassPoint: String {
case North, South, East, West
}

上面例子中,CompassPoint.South拥有隐式原始值South,依次类推。

使用枚举成员的rawValue属性可以访问该枚举成员的原始值:

let earthsOrder = Planet.Earth.rawValue
// earthsOrder 值为 3

let sunsetDirection = CompassPoint.West.rawValue
// sunsetDirection 值为 "West”

######使用原始值初始化枚举实例(Initializing from a Raw Value)

如果在定义枚举类型的时候使用了原始值,那么将会自动获得一个初始化方法,这个方法接收一个叫做rawValue的参数,参数类型即为原始值类型,返回值则是枚举成员或nil。你可以使用这个初始化方法来创建一个新的枚举实例
#####递归枚举(Recursive Enumerations)
递归枚举(recursive enumeration)是一种枚举类型,它有一个或多个枚举成员使用该枚举类型的实例作为关联值。使用递归枚举时,编译器会插入一个间接层。你可以在枚举成员前加上indirect来表示该成员可递归。

这些只是对枚举的大体介绍,具体的解释请查阅文档.
####项目实例
做好了铺垫,接下来就说一下枚举在项目中的使用,我在大牛的代码里面看见一个功能,截图如下:
![屏幕快照 2016-03-14 22.31.08.png](http://upload-images.jianshu.io/upload_images/668737-9964686e49d1fb43.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
如果按我思路的话就是利用tableView,结果我看大牛是用了枚举来做的,感觉特别有意思,所以在此作为记录.
言归正传,上代码:

1 首先定义支付类型的枚举:

声明支付方式的枚举类型,这里我们可以看到给每个枚举赋了原始值,它的作用在下面将会体现出来
enum PayMethodsType: Int {
case WeChat = 0
case QQ = 1
case AliPay = 2
case Delivery = 3
}

2 自定义一个View用来表示每种支付方式的小组件:
![屏幕快照 2016-03-14 23.35.52.png](http://upload-images.jianshu.io/upload_images/668737-88c6ab46c5a0b151.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

//MARK:-支付类型View
class PayMethodsView: UIView {

//支付类型
private var payType: PayMethodsType?
//支付类型的图标
private let payIconImageView = UIImageView(frame: CGRectMake(20, 10, 20, 20))
//支付类型的名称
private let payTitleLabel:UILabel = UILabel(frame: CGRectMake(55,0, 150, 40))
//被选中的支付类型回调
private var selectedCallBlock:((type: PayMethodsType) -> Void)?
//每种支付类型中的选择按钮
let selectedBtn: UIButton = UIButton(frame: CGRectMake(ScreenWidth - 10 - 16, (40 - 16) * 0.5, 16, 16))

//MARK:-重写init方法 在init中初始化每个控件
override init(frame: CGRect) {
    super.init(frame: frame)
    
    payIconImageView.contentMode = UIViewContentMode.ScaleAspectFill
    addSubview(payIconImageView)
    
    payTitleLabel.textColor = UIColor.blackColor()
    payTitleLabel.font = UIFont.systemFontOfSize(14)
    addSubview(payTitleLabel)
    
    selectedBtn.setImage(UIImage(named: "v2_noselected"), forState: .Normal)
    selectedBtn.setImage(UIImage(named: "v2_selected"), forState: .Selected)
    selectedBtn.userInteractionEnabled = false
    addSubview(selectedBtn)
    
    lineView(CGRectMake(15, 0, ScreenWidth - 15, 0.5))
    
    //手势
    let tap = UITapGestureRecognizer(target: self, action: "selectedPayView")
    addGestureRecognizer(tap)
    
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

//线
private func lineView(frame:CGRect) {
    let lineView: UIView = UIView(frame: frame)
    lineView.backgroundColor = UIColor.blackColor()
    lineView.alpha = 0.1
    addSubview(lineView)
}

//便利构造法
convenience init(frame: CGRect, payType:PayMethodsType, selectedCallBlock: ((type:PayMethodsType) -> ())) {
    self.init(frame:frame)
    self.payType = payType
    
    //根据枚举进行判断
    switch payType {
    case .WeChat:
        payIconImageView.image = UIImage(named: "v2_weixin")
        payTitleLabel.text = "微信支付"
        break
    case .QQ:
        payIconImageView.image = UIImage(named: "icon_qq")
        payTitleLabel.text = "QQ钱包"
        break
    case .AliPay:
        payIconImageView.image = UIImage(named: "zhifubaoA")
        payTitleLabel.text = "支付宝支付"
        break
    case .Delivery:
        payIconImageView.image = UIImage(named: "v2_dao")
        payTitleLabel.text = "货到付款"
        break
    }
    self.selectedCallBlock = selectedCallBlock
}
//MARK:Tap Action
func selectedPayView() {
    selectedBtn.selected = true
    if selectedCallBlock != nil && payType != nil {
        selectedCallBlock!(type: payType!)
    }
}

}

我们可以看见在```PayMethodsView```这个类中,将view中的元素声明出来,在这里我们声明了一个回调函数,表示被选中的支付类型回调方法,在init方法中 给view添加手势,这个手势方法中

func selectedPayView() {
selectedBtn.selected = true
if selectedCallBlock != nil && payType != nil {
selectedCallBlock!(type: payType!)
}
}

用来传递点击回调的闭包.将枚举类型Type作为参数传递.

在这个```PayMethodsView```类中用到了便利构造法,在另一个类中创建继承自```PayMethodsView```子类的时候用便利构造法给所需要创建的view初始化出一个专属的样式.在```convenience init```中,根据枚举进行判断给view中的空间自定义image和text.

3 支付方式主题界面:

//MARK:-支付界面View
class PayView: UIView {
private var weChatView: PayMethodsView?
private var qqPurseView:PayMethodsView?
private var alipayView: PayMethodsView?
private var deliveryView:PayMethodsView?

override init(frame: CGRect) {
    super.init(frame: frame)
    
    //注意:用weak修饰self 避免在闭包中的循环引用
    weak var tmpSelf = self
    
    //在支付界面初始化每一项具体的类型的支付方式view的时候 用上面先写好的便利构造法的初始化方式,这里便利构造法中我们已经为此界面量身定做了一套专属的view排版
    weChatView = PayMethodsView(frame: CGRectMake(0, 0, ScreenWidth, 40), payType: .WeChat, selectedCallBlock: { (type) -> () in
        tmpSelf?.setSelectedPayView(type)
        print("微信支付")
    })
    weChatView?.selectedBtn.selected = true
    qqPurseView = PayMethodsView(frame: CGRectMake(0, 40, ScreenWidth, 40), payType: .QQ, selectedCallBlock: { (type) -> () in
        tmpSelf?.setSelectedPayView(type)
        print("QQ钱包")
    })
    alipayView = PayMethodsView(frame: CGRectMake(0, 80, ScreenWidth, 40), payType: .AliPay, selectedCallBlock: { (type) -> () in
        tmpSelf?.setSelectedPayView(type)
        print("支付宝支付")
    })
    deliveryView = PayMethodsView(frame: CGRectMake(0, 120, ScreenWidth, 40), payType: .Delivery, selectedCallBlock: { (type) -> () in
        tmpSelf?.setSelectedPayView(type)
        print("货到付款")
    })
    
    addSubview(weChatView!)
    addSubview(qqPurseView!)
    addSubview(alipayView!)
    addSubview(deliveryView!)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}


//MARK:-根据枚举类型的原始值对支付类型的view进行选择操作
func setSelectedPayView(type: PayMethodsType) {
    
    weChatView?.selectedBtn.selected = type.rawValue == PayMethodsType.WeChat.rawValue
    qqPurseView?.selectedBtn.selected = type.rawValue == PayMethodsType.QQ.rawValue
    alipayView?.selectedBtn.selected = type.rawValue == PayMethodsType.AliPay.rawValue
    deliveryView?.selectedBtn.selected = type.rawValue == PayMethodsType.Delivery.rawValue
}

}

private var weChatView: PayMethodsView?
private var qqPurseView:PayMethodsView?
private var alipayView: PayMethodsView?
private var deliveryView:PayMethodsView?

每个view都继承自我们刚刚创建的```PayMethodsView```类
利用```convenience init```进行对象的初始化,我们每点击一次支付方式的选项都会执行```tap```的```selectedPayView```方法,将Type通过闭包传到

func setSelectedPayView(type: PayMethodsType) {

    weChatView?.selectedBtn.selected = type.rawValue == PayMethodsType.WeChat.rawValue
    qqPurseView?.selectedBtn.selected = type.rawValue == PayMethodsType.QQ.rawValue
    alipayView?.selectedBtn.selected = type.rawValue == PayMethodsType.AliPay.rawValue
    deliveryView?.selectedBtn.selected = type.rawValue == PayMethodsType.Delivery.rawValue
}
这个函数中,然后通过枚举的原始值进行```selectedBtn.selected```的判断,在这个函数中,从上到下都会执行一遍,直到找到枚举原始值相等的时候才会给```selectedBtn```做出判断.

4 在控制器中:

//MARK:- 创建支付界面
private func buildPayView() {

    let payBaseView = UIView(frame: CGRectMake(0, 100, ScreenWidth, 190))
    payBaseView.backgroundColor = UIColor.whiteColor()
    view.addSubview(payBaseView)
    
    buildLabel(CGRectMake(15, 0, 150, 30), textColor: UIColor.lightGrayColor(), font: 12, addView: payBaseView, text: "选择支付方式")
    
    let payView: PayView = PayView(frame: CGRectMake(0, 30, ScreenWidth, 160))
    payBaseView.addSubview(payView)
    
    let lineView = createLineView(CGRectMake(0, 189, ScreenWidth, 1))
    payBaseView.addSubview(lineView)
    
}
参考了:维尼的小熊 《iOS高仿爱鲜蜂 》http://www.jianshu.com/p/879f58fe3542

swiftCafe 《Swift 中的枚举,你应该了解的东西》
http://www.jianshu.com/p/288873e6f5a4

 极客学院. “The Swift Programming Language 中文版”。 iBooks. 

本demo源代码:https://github.com/iOSJason/SwiftENUM_UsingMethodDemo.git
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值