本文转载自:代码手工艺人的博客,原文名称:Swift之 ? 和 !

Swift语言使用var定义变量,但和别的语言不同,Swift里不会自动给变量赋初始值,也就是说变量不会有默认值,所以要求使用变量之前必须要对其初始化。如果在使用变量之前不进行初始化就会报错:

  1. var stringValue : String
  2. //error: variable 'stringValue' used before being initialized
  3. //let hashValue = stringValue.hashValue
  4. //                            ^
  5. let hashValue = stringValue.hashValue

上面了解到的是普通值,接下来Optional值要上场了。经喵神提醒,Optional其实是个enum,里面有NoneSome两种类型。其实所谓的nil就是Optional.None, 非nil就是Optional.Some, 然后会通过Some(T)包装(wrap)原始值,这也是为什么在使用Optional的时候要拆包(从enum里取出来原始值)的原因, 也是PlayGround会把Optional值显示为类似{Some "hello world"}的原因,这里是enum Optional的定义:

  1. enum Optional<T> : LogicValue, Reflectable {
  2. case None
  3. case Some(T)
  4. init()
  5. init(_ some: T)
  6. /// Allow use in a Boolean context.
  7. func getLogicValue() -> Bool
  8. /// Haskell's fmap, which was mis-named
  9. func map<U>(f: (T) -> U) -> U?
  10. func getMirror() -> Mirror
  11. }

声明为Optional只需要在类型后面紧跟一个?即可。如:

  1. var strValue: String?   //?相当于下面这种写法的语法糖
  2. var strValue: Optional<Int>

一旦声明为Optional的,如果不显式的赋值就会有个默认值nil。判断一个Optional的值是否有值,可以用if来判断:

  1. if strValue {
  2. //do sth with strValue
  3. }

然后怎么使用Optional值呢?文档中也有提到说,在使用Optional值的时候需要在具体的操作,比如调用方法、属性、下标索引等前面需要加上一个?,经喵神指正,”Optional Chaining的问号的意思是询问是否响应后面这个方法,和原来的isResponseToSelector有些类似”,如果是nil值,也就是Optional.None,固然不能响应后面的方法,所以就会跳过,如果有值,就是Optional.Some,可能就会拆包(unwrap),然后对拆包后的值执行后面的操作,比如:

  1. let hashValue = strValue?.hashValue

strValue是Optional的字符串,如果strValue是nil,则hashValue也为nil,如果strValue不为nil,hashValue就是strValue字符串的哈希值

到这里我们看到了?的两种使用场景:
1.声明Optional值变量
2.用在对Optional值操作中,用来判断是否能响应后面的操作

另外,对于Optional值,不能直接进行操作,否则会报错:

  1. //error: 'String?' does not have a member named 'hashValue'
  2. //let hashValue = strValue.hashValue
  3. //                ^        ~~~~~~~~~
  4. let hashValue = strValue.hashValue

上面提到Optional值需要拆包(unwrap)后才能得到原来值,然后才能对其操作,那怎么来拆包呢?拆包提到了几种方法,一种是Optional Binding, 比如:

  1. if let str = strValue {
  2. let hashValue = str.hashValue
  3. }

还有一种是在具体的操作前添加!符号,好吧,这又是什么诡异的语法?!

直接上例子,strValue是Optional的String:

  1. let hashValue = strValue!.hashValue

这里的!表示“我确定这里的的strValue一定是非nil的,尽情调用吧” ,比如这种情况:

  1. if strValue {
  2. let hashValue = strValue!.hashValue
  3. }

{}里的strValue一定是非nil的,所以就能直接加上!,强制拆包(unwrap)并执行后面的操作。 当然如果不加判断,strValue不小心为nil的话,就会出错,crash掉。

考虑下这一种情况,我们有一个自定义的MyViewController类,类中有一个属性是myLabel,myLabel是在viewDidLoad中进行初始化。因为是在viewDidLoad中初始化,所以不能直接声明为普通值:var myLabel : UILabel,因为非Optional的变量必须在声明时或者构造器中进行初始化,但我们是想在viewDidLoad中初始化,所以就只能声明为Optional:var myLabel: UILabel?, 虽然我们确定在viewDidLoad中会初始化,并且在ViewController的生命周期内不会置为nil,但是在对myLabel操作时,每次依然要加上!来强制拆包(在读取值的时候,也可以用?,谢谢iPresent在回复中提醒),比如:

  1. myLabel!.text = "text"
  2. myLabel!.frame = CGRectMake(0, 0, 10, 10)
  3. ...

对于这种类型的值,我们可以直接这么声明:var myLabel: UILabel!, 果然是高(hao)大(gui)上(yi)的语法!, 这种是特殊的Optional,称为Implicitly Unwrapped Optionals, 直译就是隐式拆包的Optional,就等于说你每次对这种类型的值操作时,都会自动在操作前补上一个!进行拆包,然后在执行后面的操作,当然如果该值是nil,也一样会报错crash掉。

  1. var myLabel: UILabel!  //!相当于下面这种写法的语法糖
  2. var myLabel: ImplicitlyUnwrappedOptional<UILabel>

那么!大概也有两种使用场景
1.强制对Optional值进行拆包(unwrap)
2.声明Implicitly Unwrapped Optionals值,一般用于类中的属性

Swift是门新生的语言,我们有幸见证了它的诞生,激动之余也在佩服苹果大刀阔斧的推出一个新的语言替代一个已经比较成熟语言的魄力,今天在知乎 日报上看到一个回答是说Swift是一门玩具语言,正当想去吐槽,发现回答已经被删除了。个人认为苹果是很认真的推出Swift的,从Swift的各种细 微的设计也能看的出来。

另外这两个小符号就花费了我不少的时间来理解,可能依然会有错误和不妥之处,欢迎大家指正,本文旨在抛砖引玉。除此之外,Swift还有很多很棒的特性,WWDC 2014 会有四五个和Swift语言相关的Video,大家也可以去关注一下。

最后要感谢喵神的纠正了多处有问题的地方,thx, have fun!

主要参考自苹果的官方文档《The Swift Programming Language》,可以在这里下载到

Swift中可选类型(Optional)的用法 以及? 和 ! 的区别 (转载博客,知识分享)的更多相关文章

  1. Swift中的类型属性(静态变量)

    http://blog.haohtml.com/archives/15098 Swift中的类型属性(静态变量) Posted on 2014/06/13 类型属性语法 在 C 或 Objective ...

  2. 在MyEclipse8.6中设置jQuery自动提示 - 肖飞figo的云计算专栏 - 博客频道 - CSDN.NET

    body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...

  3. PhpStorm中如何配置SVN,详细操作方法 - 郑加全的博客 - CSDN博客

      登录|注册       郑加全的博客       目录视图 摘要视图 订阅 CSDN日报0711——<离开校园,入职阿里,开启新的程序人生>      征文 | 你会为 AI 转型么? ...

  4. Swift可选类型(Optional)之星耀

    首先我们先看下Objective-C与Swift语言对于可选nil的不同理解: Objective-C中的nil:表示缺少一个合法的对象,是指向不存在对象的指针,对结构体.枚举等类型不起作用(会返回N ...

  5. iOS开发零基础--Swift教程 可选类型

    可选类型的介绍 注意: 可选类型时swift中较难理解的一个知识点 暂时先了解,多利用Xcode的提示来使用 随着学习的深入,慢慢理解其中的原理和好处 概念: 在OC开发中,如果一个变量暂停不使用,可 ...

  6. swift的可选值(optional)

    苹果那文档写了一大堆也没有好好的写一下可选值(optional)这个东西.就是在有一个“Optional Chaining”的章节,但是也不是很充分的说明.最后找了半天在“the basics”里墨迹 ...

  7. go中字符串类型string的用法

    示例 // 字符串类型string的用法 package main import ( "fmt" "unsafe" ) func main() { // 字符串 ...

  8. java和数据库中日期类型的常见用法

    (1)java中日期类型:Date.Timestamp(2)数据库中:Date.Timestamp(3)字符串和Date之间的格式化转换:    SimpleDateFormat类方法: format ...

  9. mysql中字符串类型char(n)和varchar(n)的区别

    n的含义 根据网络上找到的结果(不能保证准确),在5.0.3以后版本中,n均代表字符数,而不是字节数:我用来测试的版本是5.7.20,该版本中,n表示字符数. 验证过程如下 建表 CREATE TAB ...

随机推荐

  1. wcf纯代码创建控制台应用

    https://svn.apache.org/repos/asf/incubator/stonehenge/contrib/stocktrader/dotnet/ stocktrader项目的dotn ...

  2. vector,list,deque容器的迭代器简单介绍

    我们知道标准库中的容器有vector,list和deque.另外还有slist,只不过它不是标准容器.而谈到容器,我们不得不知道进行容器一切操作的利器---迭代器.而在了解迭代器之前,我们得先知道每个 ...

  3. tyvj P1952 Easy(递推+期望)

    P1952 Easy 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 某一天WJMZBMR在打osu~~~但是他太弱逼了,有些地方完全靠运气:(我们来简化一下 ...

  4. Bzoj 1222: [HNOI2001]产品加工 动态规划

    1222: [HNOI2001]产品加工 Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 486  Solved: 298[Submit][Status ...

  5. Circle - SGU 130(递推)

    题目大意:一个圆上有2K个点,用K个线把他们连接起来,求出这些线最少可以把这个圆分成P部分,有N种分割方法.输出N和P. 分析:分割线一定是相互不相交的线,所以可以把这写分成两部分,f[i] += f ...

  6. UVA 465 (13.08.02)

     Overflow  Write a program that reads an expression consisting of twonon-negative integer and an ope ...

  7. java小数点的两种处理方法

    1. java.text.DecimalFormat;        //此方法为四舍五入 例如:DecimalFormat df = new DecimalFormat("#.0" ...

  8. linux —— shell 编程(文本处理)

    导读 本文为博文linux —— shell 编程(整体框架与基础笔记)的第4小点的拓展.(本文所有语句的测试均在 Ubuntu 16.04 LTS 上进行) 目录 基本文本处理 流编辑器sed aw ...

  9. 关于无光盘无u盘状态下该如何安装系统

    看到好东西,跟大家分享一下,需要装系统的可以作为参考资料 无光盘无u盘状态下该如何安装系统 重点  : 安装虚拟光驱(用来打开镜像文件) 一个你要安装的系统文件的iso镜像文件 http://www. ...

  10. 二进制文件和ASCII文件有何差别

    二进制文件和ASCII文件(即文本文件)的差别,对于和计算机亲近时间尚短的同学是个难题.本文用简单的样例,试图展示当中的道道,希望能对菜鸟们有些帮助. 1.一个样例:两种100000 有程序: #in ...