美文网首页SwiftOptional Swift编程珠玑iOS点点滴滴
[Swift2.0系列]新的匹配解包方式(初稿)

[Swift2.0系列]新的匹配解包方式(初稿)

作者: NinthDay | 来源:发表于2015-09-30 13:23 被阅读1524次

    Optional Pattern

    更新历史:

    1. 2015.10.31新增case-let其他写法

    当变量存在值有可能缺失的情况下使用可选类型,官方文档如下定义:

    • There is a value ,and it equals x,值存在且等于x.
    • There isn't a value at all,值不存在!

    本文今天不涉及基础语法,更多有关可选类型的内容,请看Why coding like this--自己创建一个可选类型一文。

    Swift1.2和Swift2.0 解包方式

    Swift1.2

    早前我们都喜欢使用if-let或者??进行可选类型进行解包,形如:

    //这是一个整数可选类型
    let someOptional:Int? = 42   //你可以改成nil试试 会发现没有输出了
    
    //以前的解包方式
    if let x = someOptional{
      print("someOptional value is \(x)")
    }
    var y = someOptional ?? 4
    

    Swift2.0

    而如今,Swift2.0又一次创新,新增如下两种方式。不如先一睹风采:

    //1
    //新增使用enumeration匹配 也就是枚举匹配方式
    if case .Some(let x) = someOptional{
      print("someOptional value is \(x)") //如果为nil 情况 可不会输出东西 因为匹配的是Some!
    }
    //2
    //新增使用可选模式匹配
    
    if case let x? = someOptional{
      print("someOptional value is \(x)") //不需要对x进行解包之类的东东
    }
    

    可选类型是一个枚举,存在case None 以及 case Some(T)两种情况,其中T是包裹的值。

    对于case .Some(let x) = someOptional这种匹配模式,右边的someOptional是一个可选类型,完整定义是:let someOptional:Int? = 42,换种方式写成case .Some(42)显然两者是匹配的,那么顺水推舟般x = 42喽。倘若someOptional = nil了呢?依旧转换成case .None,这时候左右两边是不匹配的! 有关更多匹配文章,请见swift.gg站点文章。

    对于case let x? 其实和case .Some(let x)是一个道理。

    两种解包优势在哪里?

    有人问if-let解包 和 if case let x? 解包有什么区别?说实话,博主目前也不清楚。希望有人告知,-

    这并不意味着if case let x?没有存在的价值,例如

    let arrayOptionalInts:[Int?] = [nil,1,2,3,nil,5]    //数组的类型是Int? 可选类型喽
    
    //遍历是用for-in  
    //swift 1.2写法
    
    for x in arrayOptionalInts{
      if let y = x{
        print("Found a \(y)")//把非 nil 值输出来
      }
    }
    
    //swift 2.0写法
    //把解包行为提前到for 语句中了
    for case let number? in arrayOptionalInts{
      print("Found a \(number)")
    }
    

    有对比才有发现,确实这时候新语法更胜一筹。

    拓展

    下面我写了一个小例子,以角色游戏为背景,游戏中有玩家、NPC和怪物。如下声明:

    // 游戏角色 有玩家 NPC 怪兽
    enum GameRole{
        case Player(name:String)// 玩家要有名字
        case NPC(name:String,faction:String)//名字 所属阵营
        case Monster(name:String,element:Int)//怪物名字 属性 水火金木土 对应1-5
    }
    
    
    var roles = [
        GameRole.Player(name: "玩家一"),
        GameRole.Player(name: "玩家二"),
        GameRole.Player(name: "玩家三"),
        GameRole.Player(name: "玩家四"),
        GameRole.NPC(name: "NPC1", faction: "光明"),
        GameRole.NPC(name: "NPC2", faction: "黑暗"),
        GameRole.NPC(name: "NPC3", faction: "精灵"),
        GameRole.NPC(name: "NPC4", faction: "黑暗"),
        GameRole.Monster(name: "怪物1", element: 1),
        GameRole.Monster(name: "怪物2", element: 2),
        GameRole.Monster(name: "怪物3", element: 4),
        GameRole.Monster(name: "怪物4", element: 5),
    ]
    
    // 早前使用方法
    // 遍历整个角色
    for role in roles{
        // 因为是枚举 所以要switch来匹配
        switch role{
        case .NPC:
            print("有 NPC 出没")
        default:
            break
        }
    }
    

    可以看到想要遍历所有roles中的NPC 比如先用for-in循环,随后再用switch来进行匹配找到NPC。代码过于冗余,甚是不爽啊。好在Swift2.0中引入的case let解包方式,以下会让你耳目一新:

    for case .NPC in roles{
        print("NPC找到")
    }
    

    倘若我还想要NPC中关联的名字以及阵营呢?

    for case let .NPC(name,faction) in roles{
        print("NPC找到 name:\(name) 阵营:\(faction)")
    }
    

    苛刻一点 我只想要黑暗阵营的NPC!

    for case let .NPC(name,faction) in roles where faction == "黑暗"{
        print("NPC找到 name:\(name) 阵营:\(faction)")
    }
    

    恩.可能你还看不惯case-let这种写法,或许你对其还是无感。但是我若是这么写呢?

    (2015.10.31更新)

    for case .NPC(let  name, let  faction) in roles where faction == "黑暗"{
        print("NPC找到 name:\(name) 阵营:\(faction)")
    }
    

    如此纯正的枚举匹配,为此你还有疑惑? 倘若需要自定义匹配模式,需要重载func ~=(pattern:value)这一方法。

    倘若你觉得文章不错,请关注我,点击喜欢。另外推荐swift技术群:392436022。

    相关文章

      网友评论

        本文标题:[Swift2.0系列]新的匹配解包方式(初稿)

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