swift开发之optional类型的理解和使用

tips:本人开发经验不多,如文章有概念错误,还请各位指正,原创文章,转载请注明出处。


首先看下swift内部对于optional类型的数据结构的定义。

public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible {
    case None
    case Some(Wrapped)
    /// Construct a `nil` instance.
    public init()
    /// Construct a non-`nil` instance that stores `some`.
    public init(_ some: Wrapped)
    /// If `self == nil`, returns `nil`.  Otherwise, returns `f(self!)`.
    @warn_unused_result
    public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U?
    /// Returns `nil` if `self` is nil, `f(self!)` otherwise.
    @warn_unused_result
    public func flatMap<U>(@noescape f: (Wrapped) throws -> U?) rethrows -> U?
    /// Create an instance initialized with `nil`.
    public init(nilLiteral: ())
}



optional类型是一个枚举类型,有两个枚举值

1、None类型

2、Some(Wrapped)

这两个类型决定了optional类型的概念和含义,有值或者没有值:

1)optional.None表示该类型没有值,也就是nil。(特别声明,swift中的nil不在有指针含义,而是表示且仅表示optional的.None)。

2)optional.Some(Wrapped)这是表示有值的情况,Some类似于java或者c++的泛类型的含义,Wrapped 类似是封装的值。

optional的wrap和unwrap

使用optional类型,该类型会对赋值过程和取值进行一些处理。

1)赋值也被称为装包的过程(wrap),optional类型会获取当前值的类型和具体值,如int类型的数字100.当一个optional类型被赋值为这个值时,其实optional记录了对应的类型(some)int,和值部分(wrapped)100.

2)取值也被称为解包的过程(unwrap),optional根据记录的类型(some)如上面说的int,和值部分(wrapped)100,新建一个some(wrapped)同int(100)返回给程序


如何声明一个optional类型?

声明optional类型十分简单,我们平常声明一个字符类型是这样的

let str : String



如果想声明一个optional类型,只需要
let str : String?



或者
let str : String!



在类型后面加一个?或者!,那么你现在持有的这个变量就是optional类型变量了。十分简单。


?和!声明的optional类型有什么不同呢?

上面我们提到了optional的使用过程有装包和解包的过程,装包过程是不需要我们自己处理,但是解包的过程是需要开发者简单处理的。而声明时使用?和!的不同就表现在解包的过程。

optional类型的解包方法有下面这些

1)直接在变量后面使用!进行解包

2)使用if或者guard语句进行解包

3)使用!声明的optional变量,使用时自动调用解包

第三点已经说出了使用!和?声明变量时的不同了,就是使用!声明的optional变量在后续的使用中,不需要再进行解包操作,当需要解包时,系统会对该变量自动解包处理。而使用?声明的optional变量则需要使用上面说明的1)或者2)其中一种方法解包,才能继续使用。

那么问题来了,既然能自动解包,那么都声明成!不就好了,还省事。optional是swift特别提出的安全类型,它的安全精髓就体现在解包这个步骤上。optional类型的解包是有崩溃的风险的。一个没有值也就是nil(optional.None)的optional变量,强行解包的话,程序是会直接crash。

var firstName : String!
print(firstName)



输出时,你会得到一个error,要是在项目中,不进行判断直接对没有值的optional变量强行解包的话,程序会crash。

所以总结来说,会crash或者得到一个error的原因就是optional类型变量在解包那一刻没有值。所以在开发过程中,如果你的optional是用!声明的,你就得确保在它的生命周期内,它不可能是nil,这是使用!声明的前提。而使用?声明虽然要在每次使用之前解包,但是我们可以在解包的过程进行一些判断操作,当变量是nil时做一些合适的处理。

如何才是安全正确的解包姿势呢?

1)使用!直接解包是粗暴的,是不温柔的,是。。。

2)swift针对optional安全类型,特别对if和guard语句做了处理,使用if和guard语句解包是安全的,温柔的,是。。。

var firstName : String?
if let tempName = firstName{
    print(tempName)
}else{
    print("firstName is nil")
}



if后面的的let语句就实现了安全解包的过程。如果 firstName有值的话,tempName能获取到firstName的值。在if语句内,可以放心使用。

guard语句也有同样的效果

guard let tempName = firstName else{
    print("firstName is nil")
    //nil时做一些特殊处理
    return
}
print(tempName)



guard语句更加突出错误时的处理,还有一个优点就是,你let声明的tempName在guard语句外可以正常使用。


总结:optional是swift特别声明的安全类型,在使用过程中如果处理得当的话可以防止以前oc上很多因为数据没值导致的crash。个人还是比较推荐使用的,虽然有时候有些解包的过程感觉特别麻烦,但这都是一道道安全门,阻断了很多crash的诞生。


转载于:https://my.oschina.net/u/2542662/blog/550013

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值