美文网首页swift
浅谈 Swift 中的解包操作

浅谈 Swift 中的解包操作

作者: QiShare | 来源:发表于2021-06-15 13:33 被阅读0次

    在 Swift 中我们会接触到可选类型 Optional,刚开始写代码时会被变量后的 ?、!、?? 等符号弄得稀里糊涂。

    首先,对于以下代码:

    var num: Int?
    num = 10
    
    if num is Optional<Int> {
      print("它是可选类型")
    } else {
      print("它是Int类型")
    }
    

    在IDE中的if上一定会出现这样一个warning:'is' test is always true。也就是说 num 不是 Int 类型,而是 Optional 类型。

    1. Optional类型

    可选类型声明,如下:

    var num : Int?
    // let num2 : Int? // let类型变量只可被初始化一次
    

    以上声明的意思是:声明了一个变量,它的值可能是一个 Int 值,也可能为 nil 。也即,实际上声明的是 Optional 类型的变量,而不是声明了一个 Int 类型的

    正是因为 num 是一个可选类型,所以它才能赋值为 nil ,var num : Int = nil,这样是不可能赋值成功的,因为Int类型中没有 nil 这个概念!在 OC 中对象都可以赋值为 nil ,但在 Swift 中能赋值为 nil 的只有 Optional 类型!

    2. 关于解包

    解包符号为 !

    如果确定一个可选类型的值一定存在,那么我们使用 !进行解包来获取它的值,或者使用 Optional Binding 来处理。

    let possiablestring: String? = "An possiable string"
    print(possiablestring!) // 强制解包 确定possiablestring的值确实存在,不需要每次都验证它的值 let strValues = possiablestring!.hashValue
    

    也可以把 隐式解包可选类型 当成对每次使用的时候自动解包的可选类型。隐式解包不是每次使用的时候 在变量/常量后面加 !,而是直接在定义的时候加 !。

    let assumString: String! = "an optional string"
    print(assumString, assumString.hashValue)
    

    ! 的使用场景:

    1. 强制对 可选选类变量 进行解包;
    2. 声明 隐式解包的可选类型变量 的时候, 一般用于类中的属性。

    3. 解包的基本思路

    使用 if let 或者 guard let,而非强制解包。对于如下方法:

    func getHeight(_ height: Float?) -> Float? {
      if height != nil {
        return height! / 100
      }
      return nil
    }
    

    以上代码中使用 ! 对height进行强制解包,然后参与运算,其中每使用一次都要进行强制解包。强制解包过程中一旦解包失败,就会引起崩溃,安全的解包行为应该是通过if let 或者guard let,这种被称为可选绑定的操作来处理的:

    // if let 
    func getHeight(_ height: Float?) -> Float? {
        if let unwrapedHeight = height {
        return unwrapedHeight / 100
      }
      return nil
    }
    
    //// guard let
    //func getHeight(_ height: Float?) -> Float? {
    //  guard let unwrapedHeight = height else {
    //    return nil
    //  }
    //  return unwrapedHeight / 100
    //}
    

    注意:
    对于 if let ,大括号中是符合条件的正常情况,而外部是非正常情况;
    对于 guard let ,guard let else中的大括号是异常情况,而外部返回的是正常情况。

    多几个前置 guard let 进行判断,有时可以让代码更具可读性。

    4. 可选链的解包

    对于以下两个类:

    class Person {
      var phone: Phone?
    }
    
    class Phone {
      var number: String?
    }
    

    解包时不必一层层进行判断,因为可选链中一旦有某个链为 nil ,那么就会返回 nil ,过程如下:

    let dora = Person()
      guard let number = dora.phone?.number else {
      return
    }
    

    5. _Nonnull、nonnull 与 可选类型 的关系

    对于拼接字符串方法,OC 中是这样:

    - (NSString *)stringByAppendingString:(NSString *)aString;
    

    Swift 中是这样:

    public mutating func append(_ other: String)
    

    仅从 API 来看,OC 的入参是很危险的,因为类型是 NSString * ,那么 nil 也可以传入,这样会崩掉,应该写成:

    - (NSString *)stringByAppendingString:(NSString * _Nonnull)aString;
    
    //// 或
    //- (NSString *)stringByAppendingString:(nonnull NSString *)aString;
    

    这样以便提示程序员,入参不能为空。Swift 则不会出现这种情况,other 后面的类型为String ,而不是 String? ,说明入参是一个非可选类型。

    参考文章:

    http://www.mamicode.com/info-detail-1160599.html
    https://www.jianshu.com/p/4bfbb0ba4d32

    相关文章

      网友评论

        本文标题:浅谈 Swift 中的解包操作

        本文链接:https://www.haomeiwen.com/subject/nyjzeltx.html