★ iOS高级:Swift入门精讲③ 01 swift编程-07可选项

前言:

本篇仅为视频学习笔记

可选项 (Optional)

★ 可选项,一般也叫可选类型,它允许将值设置为nil。

例-1

 var str: String = "123"

我们上句这段代码是字符串类型的,一开始存储的是123。那么现在,我们不能把这个变量清空吗?这个时候,我们直接写一个nil,运行一下,如下:


error

我们看到上面代码,报错了。也就是说平常我们所学的这些默认类型的话都是不能给nil值的。


例-2

这个时候,我们在细想一下,如说age变量等于10,age = nil。如下代码:


error

它也会报错,这两个都是不可以的。

综上所述:在默认情况下,是不允许给nil值的,只有你把变量声明成可选类型,它才会允许将值设置为nil。


☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃


那么,怎么声明一个可选类型呢?

★ 在类型名称后面加个 问号 ?,来定义一个可选项。

例-1

 var name: String? = "jack"
 name = nil

name是一个可选类型,可选类型就是在类型后面加上一个问好❓,所以,name可以置为nil。

例-2

 var age: Int? //  默认就是nil
 age = 10
 age = nil

如上代码,age变量我们一开始把它定义一个可选类型,因为类型后边有一个问号。然后,这个可选类型将来可以存储哪些值呢?由于我写的是Int?,所以它可存储的值有两种,一种是Int类型,一种是nil。例-1中的name变量也是一样,它将来存储的类型,要么就是字符串类型,要么就是nil。

你发现了吗?我们在定义age这个变量的时候,我是没有给它设置一个初始值的,如果你是可选类型,它初始值默认就是nil


例-3

说到这里,希望大家可以理解另外一个问题,什么问题呢?来看一下,像以前age我们是这样声明,它是没有初始值的,如下:

 var age: Int

比如举个例子,创建一个test函数,在函数内部定义一个局部变量age,如下:

 func test() {
     var age: Int
 }

然后,我们想用它,如下:

在函数内部,打印age,这样是不行的,会报错。因为age它是没有初始值的,你不要天真的以为var age: Int = 0 ,不会的。

但是一旦,你将age变量变成可选var age: Int?,其实age就有一个初始值,相当于var age: Int? = nil这么写,它们二者是等价的。


我们看一个例子,如下,可选值用在哪里?

例-4

 var array = [1,15,40,29]
 func get (_ index: Int) -> Int?{
     if index < 0 || index >= array.count { // 数组越界
         return nil
     }
     return array[index]    // 返回正常的值
 }

我们创建了一个数组 array,然后自己写了一个函数 get。这个函数的作用,你传一个下标给我,我取出下标对应位置的数组元素给你。比如说,你调用get传一个0给我,我就把1返回给你。如果,你传的是2,我就把40传给你。

你想一想,你传进来的这个下标,这个索引,有可能是越界的,比如说你传了一个负1,传了一个负2,或者说你传了一个7、8、9这些比较大的下标。明显这个数组已经越界了。像这种情况,我是没法返回数据给你的。

那么,怎么表达没法返回数据呢?我们应该返回nil,既然,返回nil,就意味着我们返回值不能写Int类型,应该写一个Int?。写一个Int?也就意味着,返回的东西,有可能是nil,也可能是Int。所以,我们就可以这样写如下get函数内部,函数体。

如果index小于0或者index大于等于我们数组的长度,这个就直接返回nil,说白了数组越界。如果你这个索引是合理的直接来一个 return array[index] ,就是返回具体的Int类型给你。

---综上:如果你这个函数的返回值,有可能返回nil,也有可能返回具体值,这个时候返回值类型就要写成?,如(Int?),也即是可选项。

如果这个get传的是1,说白了它返回的是15,但是它又是可选类型,那么到时候,打印出来的是什么呢?Optional(15),也就是说,不是直接是15。

对比-了解

如果传一个-1,因为-1是小于0的,所以打印出来是nil。传一个4,数组越界,所以打印出来的是nil。

强制解包 (Forced Unwrapping)

★ 可选项是对其它类型的一层包装,可以将它理解为一个盒子

  • 如果为nil,那么它是一个空盒子
  • 如果 不为nil,那么盒子里装的是:被包装类型的数据

比如说举个例子,

如var age: Int?这样写,它的默认值就为nil,说白了一开始的时候这个家伙是一个空盒子 。
如果要执行age = 10这句代码是,意味着将10存起来,这个时候相当于什么操作呢,相当于把10这个东西,装在了age这个空盒子里包装起来。
如果在执行age = nil这句代码,就是相当于把age这个空盒子里的10清空,相当于又会变成一个空盒子。这就类似于,将盒子里的东西倒出来,这个时候就变成了一个空盒子。


★ 如果要从可选项中取出被包装的数据(将盒子里装的东西取出来),需要使用感叹号!,进行强制解包。

例-1

如果将来我们要把这个10取出来,怎么办呢,这个时候我们就需要使用感叹号!,进行强制解包。

var age: Int? = 10这句代码,相当于把10,存储在了age: Int?这个盒子里面。现在我们想把盒子里面这个10取出来,怎么办?需要在可选类型的最右边写一个感叹号!(age!)。你只要这样写,它就会把里面的这个10取出来,赋值给ageInt,到时候ageInt这个存储的整数值为10。

那么,这个时候,在 += 10,很明显就变成了20。


例-2

 var age: Int? = 10

Int?它不是一个整数,他是一个大盒子,是对Int类型的一个包装。既然Int?不是Int,那我们思考一个问题,我们能不能var num = age + 20这样做呢?

运行一下,会报错,因为age它不是Int,既然它不是Int怎么可以跟我这个Int类型的20相加呢?默认肯定是不可以的,那怎么才能可以呢?

将你里面存储的值取出来,相当于把这个盒子里装的东西取出来

 var num = age! + 20

这样就可以了,那么这样就是10 + 20,就是30。这个就是为什么需要强制解包。

有一个问题,强制解包,就是把盒子里面的10,拿出来用一下,那么解包之后,这个age里面还有东西吗?那么,这个盒子里面的东西还在不在呢?我们打印一下:

我们打印出来还是,Optional(10),说明了强制解包只是把盒子里面的值10拿出来用一下,但是这个盒子里面依然装着这个10的。

★ 如果对值为nil的可选项(空盒子)进行强制解包,将会产生运行时错误。


所以,要注意一下,你强制解包之前,要确定盒子里面不是空的。如果是空,你强制解包,你的程序就会闪退。

那么,该怎么做呢,如下:

判断可选项是否包含值

看下面,字符串转换整数的例子

  let number = Int("123")
 if number != nil {
     print("字符串转换整数成功:\(number!)")
 } else {
     print("字符串转换整数失败")
 }
 // 字符串转换整数成功:123

上面的例子,有可能会转换失败。如果如下:

 var num = Int("kkk123")

你传的是"kkk123",它这样的话,它能转成Int类型吗?很明显是不行的,也就是说有可能会转换失败。如果把kkk删掉,它就可以转换成功。

所以,相当于Int("kkk123")这个转换,可能成功,也可能失败。所以你思考一下,如果是失败的话,你觉的它会返回什么?你可能会想,如果失败的话,返回0,返回-1,不行,你想想。因为返回0的话,肯定是有歧义的,因为有可能我们传的字符串就是0,既然,我们传的字符串就是0,那么我们返回的当然也是0。所以,任何整数代表,都是不可以的。唯有一种返回nil可以代表返回失败,才是最合适的。

Int("kkk123") 是一个可选项,所以判断代码如上面代码一样判断。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容