SwiftOptional Swift编程珠玑iOS点点滴滴

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

2015-09-30  本文已影响1524人  NinthDay

Optional Pattern

更新历史:

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

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

本文今天不涉及基础语法,更多有关可选类型的内容,请看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。

上一篇下一篇

猜你喜欢

热点阅读