枚举语法

你可以用enum开始并且用大括号包含整个定义体来定义一个枚举:

  1. enum SomeEnumeration {
  2. // 在这里定义枚举
  3. }

这里有一个例子,定义了一个包含四个方向的罗盘:

  1. enum CompassPoint {
  2. case North
  3. case South
  4. case East
  5. case West
  6. }

枚举中定义的变量(像上例中North, South, East, West)是枚举的成员变量(或者说成员).关键字case是用来标明这一行将要定义一个新的成员变量

注意:与C或者Objective-C不同的是,在Swift语言中枚举类型的成员初始的时候不会被默认赋值成整数值,在CompassPoint这个例子中,North, South, East, West默认不会隐式的等于0,1,2,3。取而代之的是不同的枚举成员将要用什么类型以及赋值什么值都是可以自己控制的,可以在定义CompassPoint这个枚举的时候指定.

多个成员还可以用一行来定义,他们之间用逗号分割:

  1. enum Plant{
  2. case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
  3. }

每个枚举的定义都是定义了一个全新的类型,就像Swfit中的其他的类型一样,枚举的名称(像上边的CompassPoint, Plant)应该是以一个大写字母开头,让他们是单数类型而不是复数类型,从而让他们可以不言而喻:

  1. var directionToHead = CompassPoint.West

当directionToHead在初始化过程中被赋值成CompassPoint中的某一个可能的值的时候,它的类型就可以被推测出来来了。一旦directionToHead被声明成是CompassPoint类型,那么你就可以简短的使用逗号表达式来给它赋值成其他的CompassPoint当中的值了:

  1. directionToHead = .East

directionToHead的类型是已知的了,所以你可以忽略它的类型来给他赋值了。这样使得在使用显示类型的枚举值时代码具有很高的可读性。

使用Switch语句来匹配枚举值

你可以通过switch语句来访问单独的某个枚举值:

  1. directionToHead = .South
  2. switch directionToHead {
  3. case .North:
  4. println("Lots of planets have a north")
  5. case .South:
  6. println("Watch out for penguins")
  7. case .East:
  8. println("Where the sun rises")
  9. case .West:
  10. println("Where the skies are blue")
  11. }
  12. // 输出"Watch out for penguins”

你可以这样阅读这段代码:考虑directionToHead的值,如果它等于.North那么就输出"Lost of planets have a north",如果它等于.South,那么就输出"Watch
out for penguins"。



就和在控制流程那一章所讲,一个switch语句被用到判断枚举值的时候,必须要包括所有的枚举成员。假设.West被忽略了,将会导致编译出错,因为它没有考虑到枚举的所有的枚举成员,我们需要全面性的确保枚举的所有成员不被忽略掉.



如果给考虑每个枚举的成员不合适,你可以提供一个default来覆盖其他没有明确处理的成员:

  1. let somePlanet = Planet.Earth
  2. switch somePlanet {
  3. case .Earth:
  4. println("Mostly harmless")
  5. default:
  6. println("Not a safe place for humans")
  7. }
  8. // 输出 "Mostly harmless"

关联值

在上一节的示例中显示了一个枚举的成员是如何在自己的权利界定(和类型)的值。你可以设置一个常量或变量的值为Planet.Earth ,然后检查这个值。然而,如果在保留成员值的同时能够存储其它类型的关联值将会变得更有意义。这使您能够在保存成员值的同时存储额外的自定义信息,并且允许每次你在代码中使用这些成员值的时候改变这些关联值。在Swift中当你定义一个枚举成员的时候,你可以给他关联任何的类型,而且如果需要的话每个成员可以有不同的关联类型。枚举类型的这个特性和其他语言当中的辨别联合,标记联合或者变体很像。



举个例子,设想一个库存跟踪系统想要通过两种不同的条形码来跟踪产品。一些产品用UPC-A格式的一维条形码标识的,使用0到9的数字。每个条形码当中有一个标识“数字系统“的数字,然后是10个“标识符"数字,最后边一个用来做“检查”的数字,以确保这个条形码被正确的扫描识别:





另一些产品是用QR编码格式的二维码标识的,这种条形码可以使用任何ISO 8859-1的字符而且最大可以编码一个2953字符长度的字符串:





如果能够用一个有三个整型的元组来存储UPC-A格式的条形码,然后用一个可以存储任意长度的字符串来存储QR格式的条形码,那么对于一个库存跟踪系统来说,将会是再便捷不过的了。



在Swift语言中,一个可以定义两个格式的产品条形码的枚举看起来是这样的:

  1. enum Barcode {
  2. case UPCA(Int, Int, Int)
  3. case QRCode(String)
  4. }

你可以这样阅读这段代码:定义了一个叫做Barcode的枚举类型,它可以有一个UPCA成员,这个成员关联了一个包含三个整型数值的元组,同时这个枚举类型还有一个QRCode成员,关联了一个字符串。



这个定义不会生成任何的整型或者字符串值,他只是定义了当一个不可变变量或者变量等于Barcode.UPCA或者Barcode.QRCode的时候它被关联的值的类型



这样一来可以用任意其中一个类型来生成一个新的条形码了:

  1. var productBarcode = Barcode.UPCA(8, 85909_51226, 3)

这个例子生成了一个新的变量叫做productBarcode,这个变量被关联了一个Barcode.UPCA类型的元组,这个元组的值为(8, 8590951226,
3),被提供做“标识”的值用下划线分割了-85909_51226,这样做是为了更好的被以条形码读出来。



同样的产品还可以被赋值为另一个条形码类型:

  1. productBarcode = .QRCode("ABCDEFGHIJKLMNOP")

在这一点上,原来的Barcode.UPCA以及关联到的整型值被一个新类型Barcode.QRCode以及与其关联的字符串给替换了。Barcode类型的不可变变量以及可变变量可以存储.UPCA或者.QRCode类型(同时还有与其相关联的值),但是每次都只能存储这两个类型当中的一个。



同样,这两个不同的类型可以用Switch语句来做检查。同时,在switch语句中他们相关联的值也可以被获取到。你可以把关联的值当做不可变变量(用let来开头),或者可变变量(用var开头)以在switch的控制体当中使用。

  1. switch productBarcode { case .UPCA(let numberSystem, let identifier, let check): println("UPC-A with value of \(numberSystem), \(identifier), \(check).") case .QRCode(let productCode): println("QR code with value of \(productCode).") }

如果一个枚举成员关联的所有值都被当做不可变变量或者可变变量来使用,那么你可以在成员名称之前只放一个let或者var来达到目的,简要示例:

  1. switch productBarcode {
  2. case let .UPCA(numberSystem, identifier, check):
  3. println("UPC-A with value of \(numberSystem), \(identifier), \(check).")
  4. case let .QRCode(productCode):
  5. println("QR code with value of \(productCode).")
  6. }
  7. // 输出 "QR code with value of ABCDEFGHIJKLMNOP.”

原始值

在上一节当中条形码的例子展示了一个枚举类型的成员怎么声明他们可以存储不同类型的关联值。不同于关联值,枚举类型的成员还可以预设置默认值(我们叫他原始值),这些值的类型是相同的。



这里有一个枚举成员存储一个ASCII值的例子:

  1. enum ASCIIControlCharacter: Character {
  2. case Tab = "\t"
  3. case LineFeed = "\n"
  4. case CarriageReturn = "\r"
  5. }

这里定义了一个原始值为字符类型的枚举类型ASCIIControlCharacter,而且包含了一些我们常用的控制字符。关于字符类型,你可以在字符串和字符那个章节找到更多的描述。



请注意,原始值与关联值不同。原始值应该是在你定义枚举的代码中被设置为预填充值的,就像上述三个ASCII码。对于一个特定的枚举成员的原始值始终是相同的。关联值是当你创建一个基于枚举的成员的新的常量或变量的时候设置的,并且每次都可以是不同的。



原始值可以是字符串,字符或者其他任何的整型或者浮点型等数字类型。每个原始值在他属的枚举类型定义的时候都应该是不同的。如果原始值是整数类型,那么当其他枚举成员没有设置原始值的时候,他们的原始值是这个整型原始值自增长设置的。



下边这个枚举类型是对之前的Plant枚举类型的改良,新的枚举类型有一个整型的原始值来标识他们在距离太阳的顺序:

  1. enum Planet: Int {
  2. case Mercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
  3. }

自增长的意思就是Planet.Venus的原始值会被设置成2,以此类推。



可以通过枚举成员的toRaw()方法来获取他的原始值:

  1. let earthsOrder = Planet.Earth.toRaw()
  2. //eathsOrder is 3

使用枚举成员的fromRaw()方法来尝试通过一个原始值来寻找他所对应的枚举成员。下面这个例子介绍了怎么通过Uranus的原始值7找到Uranus的:

  1. let possiblePlanet = Planet.fromRaw(7)
  2. // possiblePlanet is of type Planet? and equals Planet.Uranus”

然而不是所有的整型值都可以找到一个对应的Planet,正是如此,fromRaw()将会返回一个非强制类型的枚举成员。上边展示的例子当中possiblePlanet是一个Planet?类型,或者是一个非强制Planet类型。



如果你尝试通过原始值9来寻找他对应的Planet,那么fromRaw()返回给你的非强制Planet类型将会是nil:

  1. let positionToFind = 9
  2. if let somePlanet = Planet.fromRaw(positionToFind) {
  3. switch somePlanet {
  4. case .Earth:
  5. println("Mostly harmless")
  6. default:
  7. println("Not a safe place for humans")
  8. }
  9. } else {
  10. println("There isn't a planet at position \(positionToFind)")
  11. }
  12. // 输出 "There isn't a planet at position 9”

这个例子尝试使用非强制类型绑定来试着用原始值9来获取一个Planet。表达式if let somePlanet = Planet.fromRaw(9)用来检索一个Planet,如果能够检索到Planet将会将这个非强制Planet赋值给somePlanet。在这个示例中,通过原始值9不可能检索到对应的Planet,所以else包含的语句将会被执行。

【iOS】swift 枚举的更多相关文章

  1. iOS Swift WisdomHUD 提示界面框架

    iOS Swift WisdomHUD 提示界面框架  Framework Use profile(应用简介) 一:WisdomHUD简介 今天给大家介绍一款iOS的界面显示器:WisdomHUD,W ...

  2. iOS Swift WisdomKeyboardKing 键盘智能管家SDK

    iOS Swift WisdomKeyboardKing 键盘智能管家SDK [1]前言:    今天给大家推荐个好用的开源框架:WisdomKeyboardKing,方面iOS日常开发,优点和功能请 ...

  3. iOS swift的xcworkspace多项目管理(架构思想)

    iOS  swift的xcworkspace多项目管理(架构思想) 技术说明: 今天在这里分享 swift下的 xcworkspace多项目管理(架构思想),能为我们在开发中带来哪些便捷?能为我们对整 ...

  4. iOS Swift 模块练习/swift基础学习

    SWIFT项目练习     SWIFT项目练习2 iOS Swift基础知识代码 推荐:Swift学习使用知识代码软件 0.swift中的宏定义(使用方法代替宏) 一.视图  +控件 1.UIImag ...

  5. ios swift 实现饼状图进度条,swift环形进度条

    ios swift 实现饼状图进度条 // // ProgressControl.swift // L02MyProgressControl // // Created by plter on 7/2 ...

  6. Building gRPC Client iOS Swift Note Taking App

    gRPC is an universal remote procedure call framework developed by Google that has been gaining inter ...

  7. iOS Swift WisdomScanKit图片浏览器功能SDK

    iOS Swift WisdomScanKit图片浏览器功能SDK使用 一:简介      WisdomScanKit 由 Swift4.2版编写,完全兼容OC项目调用. WisdomScanKit的 ...

  8. iOS Swift WisdomScanKit二维码扫码SDK,自定义全屏拍照SDK,系统相册图片浏览,编辑SDK

    iOS Swift WisdomScanKit 是一款强大的集二维码扫码,自定义全屏拍照,系统相册图片编辑多选和系统相册图片浏览功能于一身的 Framework SDK [1]前言:    今天给大家 ...

  9. iOS swift项目IM实现,从长连接到数据流解析分析之Socket

    iOS  swift项目IM实现,从长连接到底层数据解析分析之Socket 一:项目简介:  去年开始接手了一个国企移动项目,项目的需求是实现IM即时通讯功能. * 一期版本功能包括了:       ...

随机推荐

  1. 【网络流24题】最长k可重区间集(费用流)

    [网络流24题]最长k可重区间集(费用流) 题面 Cogs Loj 洛谷 题解 首先注意一下 这道题目里面 在Cogs上直接做就行了 洛谷和Loj上需要判断数据合法,如果\(l>r\)就要交换\ ...

  2. 杜教筛:Bzoj3944: sum

    题意 求\(\sum_{i=1}^{n}\varphi(i)和\sum_{i=1}^{n}\mu(i)\) \(n <= 2^{31}-1\) 不会做啊... 只会线性筛,显然不能线性筛 这个时 ...

  3. 大文件视频断点续传插件resumabel.js,优化上传速度,缩短最后一片等待时长。

    在angular中使用resumable.js遇到的一个问题:大视频上传到99-100%时,此时正在上传最后一片,最后一片的xhr一直是pending状态.原因插件会检查第一片和最后一片的元数据,检测 ...

  4. 【MyBatis源码分析】Configuration加载(上篇)

    config.xml解析为org.w3c.dom.Document 本文首先来简单看一下MyBatis中将config.xml解析为org.w3c.dom.Document的流程,代码为上文的这部分: ...

  5. 《阿里巴巴Android编码规范》阅读纪要(二)

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 本篇继续上一篇<阿里巴巴Android编码规范>阅读纪要(一) ,还是建议各位同学有时间完整阅读一下<阿里巴巴Android编码规 ...

  6. (python走过的坑)OpenCV中错误opencv-3.3.1\modules\highgui\src\window.cpp:339: error: (-215) size.width>0 && size.height>0 in function cv::imshow

    第一次在python中使用OpenCV(cv2),运行时报错opencv-3.3.1\modules\highgui\src\window.cpp:339: error: (-215) size.wi ...

  7. dva.js 用法总结

    dva.js是阿里前端团队开发的一个基于react.redux.webpack的一个前端框架,他能够实现react-redux-webpack环境一键部署,能帮前端工程师节省不少环境搭建的时间.而且经 ...

  8. Oracle GoldenGate实现数据库同步

    前言:最近刚好在弄数据库同步,网上查了些资料再加上自己整理了一些,做个分享! 一.GoldenGate的安装 1.安装包准备 数据库版本:Oracle Database 11g Release 2(1 ...

  9. 本地安装plsql和instantclient连接linux服务器端的oracle

    当虚拟机里面的linux服务器安装好oracle之后(具体安装方法在之前的博客有说到),如何连接使用呢?连接过程中会出现什么问题呢? 1.首先我们下载instantclient的压缩包,直接解压就好, ...

  10. mount挂载与umount卸载

    mount挂载与umount卸载 author:headsen chen      2017-10-23  15:13:51 个人原创,转载请注明作者,否则依法追究法律责任 mount:挂载: eg ...