Swift: 如何理解Swift中Optional的!和?

先来说说Optional的概念,以方便之后的理解。来看一下下面的代码:

var a : String = nil              // 编译错误,String类型不能为nil
var b : String = “Hello!”

Swift 中的普通类型不再能设为nil。那如何表示这个值不存在呢?所以引进了Optional的概念:代表 nil某个具体的值。例如:

var c : String? = nil       
var d : String? = “Hello!”

String? 就是一个Optional,它既能够被具体类型赋值, 也可以赋值为nil。通过 StringOptional的比较,发现Optional 就相当于把具体类型和 nil 打包捆绑在了一起,转变成了一种新的类型。

Optional 有两种声明方法:

var apple: String?   
var bread: String!

很多人认为,声明为 String! 的变量表明该变量的值不为 nil。但是,实际上,String!String? 都是有默认值的,且默认值都为nil。我们为它们赋一个初值再打印类型来看看:

var apple: String? = “apple”   
var bread: String! = “bread”
(lldb) p apple
(String?) $R0 = “apple”
(lldb) p bread
(String?) $R1 = “bread”

发现,尽管applebread 虽然一个是 String? 一个是 String! 但是打印出来都是 String? 类型的。
所以更恰当的理解应该是:String! 只是理解意义上的不为nil,其本质还是一个 Optional,从声明来说它和 String? 完全等价,所以也能够赋值为 nil 。

为了之后叙述方便,我们把定义类似 String? 的称为 Optional(?), 定义类似 String! 的称为 Optional(!)

Optional 的本质是囊括 nil 和具体类型的一种枚举。获取它具体值的操作过程称之为拆包,用 “!” 表示。先来做个实验:

var string : String
var optionalString: String?   
var nonOptionalString: String!
string = nonOptionalString    // ① 崩溃
string = optionalString       // ② 编译错啦
string = optionalString!      // ③ 崩溃

具体看一下报错原因:

  • String! 赋值给 String ,报错为:拆包时Optional的值为nil

  • String? 赋值给 String,编译器报错为 Optional未拆包;

  • ③ 拆包后的 String? 赋值给 String,这时,报错为:拆包时Optional的值为nil

String! 和 拆包后的 String? 进行传值时报的错相同,由此我们可以得出一个结论:
编译器默认 Optional(!) 是确定有值的,所以不需要再对 nil 的情况进行处理。Optional(!) 的变量只是给予了自动拆包的权限,在实际使用它的过程中不需要再次使用 ‘!’ 进行拆包。在swift官方文档中称为:Implicitly Unwrapped Optional (隐式拆包),也可以理解成“拆过包了”。

但是,只有在变量确认有值的情况下才能进行拆包。就像如上代码,optionalStringnil,进行拆包就会引发崩溃。swift官方建议,Optional 使用 if + ! 结合的方式或者 if let 进行安全地拆包。简单的看下代码:

if optionalString != nil {
   append(string: optionalString!)
} else {
   // do something
}
if let actualString = optionalString {
   append(string: actualString)
} else {
   // do something
}

再次提醒一下,Optional(!)Optional(?) 都可以使用这两种方式进行安全地拆包,只是编译器不会对没有处理 nil 情况的 Optional(!) 报错。

下图展示了 OptionalString 可接收类型的比较:

String? String! String
String? String? String!
String! String! String
String String
nil nil

拆完包之后的 Optional其实就是 String 类型。编译器强制使用者在变量为 nil 的时候要进行处理,否则就会报错会崩溃。String! 是为了规避变量一定不为 nil 的情况下却要反复判断是否为 nil 的冗余代码而产生的。例如,我们在使用 IBOutlet 时,一定会定义成 Optiona(!)
String! 在声明时和 String? 完全等价,在使用时和 String 完全等价。

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

推荐阅读更多精彩内容

  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 2,756评论 2 9
  • 很多人在刚上手swift时对于Optional中 ‘!’ 和 ‘?’ 的使用十分不理解,接下来我会谈一谈自己对于这...
    子疯zp阅读 270评论 0 0
  • 对各种值为"空"的情况处理不当,几乎是所有Bug的来源。 在我们的例子里,尽管tmp的值是nil,但调用tmp的r...
    AKyS佐毅阅读 10,518评论 1 13
  • 关于 Swift 重要这个文档所包含的准备信息, 是关于开发的 API 和技术的。这个信息可能会改变, 根据这个文...
    无沣阅读 4,301评论 1 27
  • 文/冰雪伊人 —词曲系列— 薄暮初相许,黄昏意自聆。朔风吹尽远寒灯。沙漠落霞孤寂,无处觅倾城。 去岁微霜见,今朝暖...
    西域冰雪阅读 792评论 22 25