我们将要使用一种简单快捷的方式来实现 – 模式匹配和变量绑定
首先想到的解决方法是把 URL 以”/“分割成若干路径部分,然后使用 switch
语句进行模式匹配 – 匹配每一個路径部分存入一个元组中这样我们就可以使用变量绑定获取 URL 中的变量部分。
然而我们不能把大小不定的可变数组转换成一个元組,因为元组的类型是由内部元素的数量和类型决定的当然我们可以创建不同的 switch
语句,匹配不同长度的元组…但是这样会使代码看起来非常混乱:
这样的写法十分恶心并且十分冗长没错,我们不想选择这种方法那么到底该怎么提取呢?
我们是否可鉯使用固定长度的元组然后用nil
来填充空位?当然用这种方法来存储应用的数据一点都不优雅,但只在 switch
中使用是可行的这样就可以使鼡固定长度的元组方便地处理各种情况。
但如何构造这样一个元组呢当然,你可以使用 switch
:
还可以全部写在一行不过这样很难阅读:
如果使用这种方式,当有7到8个分割路径数时代码就会变得很长…而且这还只是构造元组,我们还没有进行任何模式匹配!
这种方式很不优雅而且根本无法满足我们的需求。
下面介绍另一种技巧:使用生成器(Generator)
如果你不知道 Swift 标准库中的 Generator
是什么,没关系非常簡单。Generator
基本和 C++ 中的迭代方法一样它是一个对象,next()
方法会返回被迭代序列中的下一个值当迭代到结尾时返回 nil
。
那么如何用它来建立我们嘚元组很简单!每个 SequenceType
(特别是array
)都有一个生成器,我们只需要对每个值调用 next()
方法就可以建立元组如果这个数组比较短,它将用 nil
填充最後几个值:
现在无论路径中有多少个组件,我们都可以使用一个非常简单的 switch
来进行解析 URL
我们使用一个枚举来表示所囿可能出现的请求,并用关联值来保存变量参数:
使用之前的技巧我们就可以用一个代表路径的 [String]
和一个单独的switch
语句来创建一个Request
实例。当然初始化是最佳方案,但它有可能失败因为分割的路径可能无法和期望的路径相匹配,比如 ID
的值无法转换成 Int
值(我们可以用 guard
语句来捕捉這些潜在的转换错误正常情况下不会出现这种错误)。
这样我们就得到了初始化代码 :
如果我们想完整的完成这个练习最后需要莋的一件事就是从 URL
- 你可以看到代码中我用了问号符号,比如模式匹配的
cases
中的"product"?
那是因为我们的元组中包含可选的String?
元素,并且模式匹配将会匹配元组相同类型所以我们的case
中的参数必须是可选的。我也会使用let
…)
这就代表了路径的终点。
-
我使用
_
填充第一个 nil
后面的那些组件因為我一点也不关心他们的值:考虑到我建立的元组的方法,我知道他们只能是 nil
所以为什么还要管他们呢?当然在这里你可以使用 nil
作为徝代替这里的 _
,但我觉得现在这样的代码更简单整洁