# Swift 模式匹配 ## 模式匹配的底层实现 为了去除其他语句对汇编研究造成的干扰,所以 case 和 default 里面都很简单,聚焦于研究 case 的模式匹配实现。测试代码如下: ```swift var age = 28 switch age { case 0...30: break default: break } ``` 在 `case 0...30:` 处加断点可以看到汇编,然后看到可疑方法 `Swift.RangeExpression.~= infix(τ_0_0, τ_0_0.Bound) -> Swift.Bool` LLDB 输入 `si` 进去窥探下 看样子,函数还没到底,看到地址 `0x00007ff81a86f530` 很大很大,猜测应该是一个系统动态库方法地址,继续跟进去研究 `si` ![](https://github.com/FantasticLBP/knowledge-kit/raw/master/assets/MemoryLayout.png) 可以看到内部还有函数调用 继续跟进 `si` 看上去是在做继续 `clasedRange` 区间符合的判断,继续跟进 `si`,里面确实是在判断是否命中区间的判断。不一一研究了,这次目的是判断 switch...case pattern 的实现。 结论:switch case pattern 模式匹配,系统底层实现是依赖 ## 模式匹配的应用 自定义模式匹配。根据上面通过汇编进行分析,我们知道 - `static func ~=(pattern: case 后面的值, value: switch 后面的值)` pattern 代表的是 case 后面的值,value 代表 switch 后面的值。 - 当 case 有不同类型的时候,如果编译报错,则需要重写 `static func ~=(pattern: ,value: )` 方法,调整 pattern 的数据类型,数据类型应该和 case 后的数据类型一致(可以是函数等) ```swift struct Student { var score = 0 var name = "" /// Student 和 Int 模式匹配的方法 /// - Parameters: /// - pattern: case 后面的内容 /// - value: switch 后面的内容 /// - Returns: 是否命中 static func ~= (pattern: Int, value: Student) -> Bool { value.score >= pattern } static func ~= (pattern: Range, value: Student) -> Bool { pattern.contains(value.score) } static func ~= (pattern: ClosedRange, value: Student) -> Bool { pattern.contains(value.score) } static func ~= (pattern: String, value: Student) -> Bool { Int(pattern) == value.score } } var student: Student = Student(score: 55, name: "杭城小刘") switch student { case 100: print(">=100") case 90: print(">=90") case 80..<90: print("[80, 90)") case 60...79: print("[60, 79]") case "55": print("斯国一") default: print("just so so") } // console 斯国一 ``` 修改 `var student: Student = Student(score: 78, name: "杭城小刘")` 则输出 `[60, 79]` ```swift extension String { static func ~=(pattern: (String) -> Bool ,value: String) -> Bool { pattern(value) } } func hasPrefix(_ prefix: String) -> (String) -> Bool { {$0.hasPrefix(prefix)} } func hasSuffix(_ prefix: String) -> (String) -> Bool { {$0.hasSuffix(prefix)} } var name = "城小刘" switch name { case hasPrefix("杭"): print("有杭哦") case hasSuffix("刘"): print("有刘哦") default: print("just a name") } // console 有刘哦 ``` ##