对于Swift中Optional的新理解

22 篇文章 0 订阅

Normal Type 和 Optional Type(可选类型)

Optional是swift不同于C以及Objective-c的一种新概念。引进了这个概念之后,我们可以把类型分为普通类型(例如, String, Array ...)和可选类型(Optional Type)。

swift中使用普通类型表示值一定存在,用可选类型(Optional Type)来表示其所对应的值可能存在可能为nil。

Optional Type 的本质是一个枚举类型,它枚举的是None(nil)和NormalType,如下所示:

 

enum Optional {
    case None
    case Normal(T)
}复制代码

所以其实OptionalType和NormalType是一个包含关系。

我们在写代码的时候也会发现,对于一个要传入NormalType的函数,如果传入一个有枚举情况的Optional的值是会报错的:

open func appending(_aString:String) ->String复制代码

 

 var stringA : String = "a"
 let stringB : String? = "b"
 stringA.appending(stringB)    // 编译错啦复制代码

Optional Type的分类

Optional Type又分为Normal Optional(普通)和Implicitly Unwrapped Optional(隐式拆包)。

普通的可选类型用 '?' 来声明,表示该值可能存在可能为nil。相当于声明了一个包含 Optional.None和Optional.Some(T)的枚举类型。

隐式拆包用 '!' 来声明,表示确认该值不为nil,一定存在。相当于声明了Optional.Some(T)。

需要注意的是,声明为隐式拆包Optional的对象值可以为nil,也就是说 'let string : String! = nil' 编译器完全是可以通过的。但是在之后访问该对象值时,会抛出异常。这和Optional Type的拆包有关。

做了个实验:

 

var stringa : String! = nil
let stringb :Character? ="a"
stringa?.append(stringb!)     // 结果为 nil
stringa.append(stringb!)     // 崩溃啦复制代码

我们发现尽管stringa是隐式拆包的Optional类型,但是通过 '?' 来访问stringa 也是可以成功操作的,不会引发崩溃。由此猜想,

stringa?.append(stringb!)复制代码

其实干了这些事:

 

if stringa != nil {
   stringa!.append(stringb!)
} else {
   return
}复制代码

由此可以得出结论,隐式拆包的Optional只是给了Optional自动拆包的权限,并不代表这个值不能够为nil。o((⊙﹏⊙))o.

Optional Type的拆包

拆包其实相当于switch & case,如下所示:

 

var y = x!
switch x {
    case Some(value) : y = value
    case None: // raise an exception
}复制代码

所以要确保x确实有值的情况下再进行拆包。

拆包的几种比较安全的办法:1)if 语句 + 强制拆包(!);2)Optional Binding (if let);

结论

1. 无论声明的String?还是String!其实都是一个Optional,所以值都可能为nil;

2. 声明为隐式拆包的Optional(例如,String!),在取值时只是省略了判断其值是否为nil的过程。所以一定要在确认值不可能为nil的情况下再使用为隐式拆包;

3. 最安全的确保一个值不为nil的情况是声明为NormalType;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值