一、字面量
-
1.1、常見字面量的默認類型
public typealias IntegerLiteralType = Int public typealias FloatLiteralType = Double public typealias BooleanLiteralType = Bool public typealias StringLiteralType = String
-
舉例,下面代碼中的10、false、"Jack" 就是字面量
var age = 10 var isRed = false var name = "Jack"
-
可以通過typealias修改字面量的默認類型,建議不要修改
typealias FloatLiteralType = Float typealias IntegerLiteralType = UInt8 var age = 10 // UInt8 var height = 1.68 // Float
Swift自帶的絕大部分類型,都支持直接通過字面量進行初始化,如:
Bool、Int、Float、Double、String、Array、Dictionary、Set、Optional
等
-
-
1.2、字面量協議, Swift自帶類型之所以能夠通過字面量初始化,是因為它們遵守了對應的協議
Bool : ExpressibleByBooleanLiteral Int : ExpressibleByIntegerLiteral Float、Double : ExpressibleByIntegerLiteral、ExpressibleByFloatLiteral Dictionary : ExpressibleByDictionaryLiteral String : ExpressibleByStringLiteral Array、Set : ExpressibleByArrayLiteral Optional : ExpressibleByNilLiteral
左邊類型,右邊協議
var b: Bool = false // ExpressibleByBooleanLiteral var i: Int = 10 // ExpressibleByIntegerLiteral var f0: Float = 10 // ExpressibleByIntegerLiteral var f1: Float = 10.0 // ExpressibleByFloatLiteral var d0: Double = 10 // ExpressibleByIntegerLiteral var d1: Double = 10.0 // ExpressibleByFloatLiteral var s: String = "jack" // ExpressibleByStringLiteral var arr: Array = [1, 2, 3] // ExpressibleByArrayLiteral var set: Set = [1, 2, 3] // ExpressibleByArrayLiteral var dict: Dictionary = ["jack" : 60] // ExpressibleByDictionaryLiteral var o: Optional<Int> = nil // ExpressibleByNilLiteral
-
1.3、字面量協議應用一
extension Int : ExpressibleByBooleanLiteral { public init(booleanLiteral value: Bool) { self = value ? 1 : 0 } } var num: Int = true print(num) // 1 class Student : ExpressibleByIntegerLiteral, ExpressibleByFloatLiteral, ExpressibleByStringLiteral, CustomStringConvertible { var name: String = "" var score: Double = 0 required init(floatLiteral value: Double) { self.score = value } required init(integerLiteral value: Int) { self.score = Double(value) } required init(stringLiteral value: String) { self.name = value } required init(unicodeScalarLiteral value: String) { self.name = value } required init(extendedGraphemeClusterLiteral value: String) { self.name = value } var description: String { "name=\(name),score=\(score)" } } var stu: Student = 90 print(stu) // name=,score=90.0 stu = 98.5 stu = 98.5 print(stu) // name=,score=98.5 stu = "Jack" stu = "Jack" print(stu) // name=Jack,score=0.0
-
1.4、字面量協議應用二
struct Point { var x = 0.0, y = 0.0 } extension Point : ExpressibleByArrayLiteral, ExpressibleByDictionaryLiteral { init(arrayLiteral elements: Double...) { guard elements.count > 0 else { return } self.x = elements[0] guard elements.count > 1 else { return } self.y = elements[1] } init(dictionaryLiteral elements: (String, Double)...) { for (k, v) in elements { if k == "x" { self.x = v } else if k == "y" { self.y = v } } } } var p: Point = [10.5, 20.5] print(p) // Point(x: 10.5, y: 20.5) p = ["x" : 11, "y" : 22] print(p) // Point(x: 11.0, y: 22.0)
二、模式匹配
-
2.1、什么是模式?
- 模式是用于匹配的規則,比如
switch
的case
、捕捉錯誤的catch、if\guard\while\for
語句的條件等 - Swift中的模式有
- 通配符模式(Wildcard Pattern)
- 標識符模式(Identifier Pattern)
- 值綁定模式(Value-Binding Pattern)
- 元組模式(Tuple Pattern)
- 枚舉Case模式(Enumeration Case Pattern)
- 可選模式(Optional Pattern)
- 類型轉換模式(Type-Casting Pattern)
- 表達式模式(Expression Pattern)
- 模式是用于匹配的規則,比如
-
2.2、通配符模式(Wildcard Pattern)
_
匹配任何值
_?
匹配非nil值enum Life { case human(name: String, age: Int?) case animal(name: String, age: Int?) } func check(_ life: Life) { switch life { case .human(let name, _): print("human", name) case .animal(let name, _?): print("animal", name) default: print("other") } } check(.human(name: "Rose", age: 20))// human Rose check(.human(name: "Jack", age: nil)) // human Jack check(.animal(name: "Dog", age: 5)) // animal Dog check(.animal(name: "Cat", age: nil)) // other
提示:平時遇到的
值?
一般都表示非nilvar num: Int? = 10 switch num { case let v?: print(v) case nil: print("nil") }
-
2.3、標識符模式(Identifier Pattern)
給對一個的常量、變量名賦值var age = 10 let name = "Jack"
-
2.4、值綁定模式(Value-Binding Pattern)
let point = (3, 2) switch point { case let (x, y): print("The point is at (\(x), \(y)).") }
-
2.5、元組模式(Tuple Pattern)
let points = [(0, 0), (1, 0), (2, 0)] for (x, _) in points { print(x) } let name: String? = "jack" let age = 18 let info: Any = [1, 2] switch (name, age, info) { case (_?, _ , _ as String): print("case") default: print("default") } // default var scores = ["joan" : 8,"jack" : 98, "rose" : 100, "kate" : 86] for (name, score) in scores { print(name, score) }
-
2.6、枚舉Case模式(Enumeration Case Pattern)
if case
語句等價于只有1
個case
的switch
語句let age = 2 // 原來的寫法 if age >= 0 && age <= 9 { print("[0, 9]") } // 枚舉Case模式 if case 0...9 = age { print("[0, 9]") } func test() { guard case 0...9 = age else { print("不在此范圍") return } print("[0, 9]") } test() switch age { case 0...9: print("[0, 9]") default: break } let ages: [Int?] = [2, 3, nil, 5] for case nil in ages { print("有nil值") break } let points = [(1, 0), (2, 1), (3, 0)] for case let (x, 0) in points { print(x) } // 1 3
-
2.7、可選模式(Optional Pattern)
-
不為 nil
let age: Int? = 42 if case .some(let x) = age { print(x) } if case let x? = age { print(x) }
-
匹配
case let age? in ages
中的age?
不為nil
let ages: [Int?] = [nil, 2, 3, nil, 5] for case let age? in ages { // 2 3 5 print(age) }
提示:上面的代碼等價于下面的
let ages1: [Int?] = [nil, 2, 3, nil, 5] for item in ages1 { if let age = item { print(age) } }
-
多個case匹配
func check(_ num: Int?) { switch num { case 2?: print("2") case 4?: print("4") case 6?: print("6") case _?: print("other") case _: print("nil") } } check(4) // 4 check(8) // other check(nil) // nil
提示:
2?
代表值不為nil,值為 2;_?
代表值不為nil,什么值都可以;_
代表任何值都可以 -
下面兩段代碼等效
var age: Int? = 10 switch age { case let x?: print(x) case nil: print("nil") } switch age { case .some(let x): print(x) case .none: print("nil") }
枚舉就只有:
none
和some
-
-
2.8、類型轉換模式(Type-Casting Pattern)
let num: Any = 6 switch num { case is Int: // 編譯器依然認為num是Any類型 print("is Int", num) // case let n as Int: // print("as Int", n + 1) default: break }
提示:
case is Int
是在匹配 num 是不是 Int 類型-
case let n as Int:
在匹配的時候 num 還是Any 類型,但是 n 是 Int 類型
class Animal { func eat() { print(type(of: self), "eat") } } class Dog : Animal { func run() { print(type(of: self), "run") } } class Cat : Animal { func jump() { print(type(of: self), "jump") } } func check(_ animal: Animal) { switch animal { case let dog as Dog: dog.eat() dog.run() case is Cat: animal.eat() default: break } } // Dog eat // Dog run check(Dog()) // Cat eat check(Cat())
重點指出的是:
check(Cat())
在執行的時候,case is Cat:
里面調用的是animal.eat()
,打印的是Cat eat
,那是因為type(of: self)
可以識別是誰在真的調用,在case is Cat:
里面是只能調用Animal
類里面的方法的 -
-
2.9、表達式模式(Expression Pattern)
-
表達式模式用在 case 中
let point = (1, 2) switch point { case (0, 0): print("(0, 0) is at the origin.") case (-2...2, -2...2): print("(\(point.0), \(point.1)) is near the origin.") default: // (1, 2) is near the origin. print("The point is at (\(point.0), \(point.1)).") }
-
自定義表達式模式 1 :可以通過重載運算符,自定義表達式模式的匹配規則,比較復雜的switch 是調用
~=
運算符struct Student { var score = 0, name = "" static func ~= (pattern: Int, value: Student) -> Bool { value.score >= pattern } static func ~= (pattern: ClosedRange<Int>, value: Student) -> Bool { pattern.contains(value.score) } static func ~= (pattern: Range<Int>, value: Student) -> Bool { pattern.contains(value.score) } } var stu = Student(score: 75, name: "Jack") switch stu { case 100: print(">= 100") case 90: print(">= 90") case 80..<90: print("[80, 90)") case 60...79: print("[60, 79]") // [60, 79] case 0: print(">= 0") default: break }
在重載
~=
運算符的時候,有些格式是固定的,如:static func ~= (pattern: Int, value: Student) -> Bool
:pattern 是case后面放的東西,value 是 switch 里面放的東西,返回值 Bool 是固定的if case 60 = stu { print(">= 60") // >= 60 } var info = (Student(score: 70, name: "Jack"), "及格") switch info { case let (60, text): print(text) // 及格 default: break }
-
自定義表達式模式 2 :匹配字符串
前綴
和后綴
的模式extension String { static func ~= (pattern: (String) -> Bool, value: String) -> Bool { pattern(value) } } func hasPrefix(_ prefix: String) -> ((String) -> Bool) { { $0.hasPrefix(prefix) } } func hasSuffix(_ suffix: String) -> ((String) -> Bool) { { $0.hasSuffix(suffix) } } var str = "jack" switch str { case hasPrefix("j"), hasSuffix("k"): print("以j開頭,以k結尾") default: break }
提示:hasPrefix 后面的
{ { $0.hasPrefix(prefix) } }
是簡寫,全部代碼如下,同樣func hasPrefix(_ prefix: String) -> ((String) -> Bool) { return { (str: String) -> Bool in str.hasPrefix(prefix) } }
-
自定義表達式模式 3 :奇數和偶數的判斷
func isEven(_ i: Int) -> Bool { i % 2 == 0 } func isOdd(_ i: Int) -> Bool { i % 2 != 0 } extension Int { static func ~= (pattern: (Int) -> Bool, value: Int) -> Bool { pattern(value) } } var age = 9 switch age { case isEven: print("偶數") case isOdd: print("奇數") default: print("其他") }
-
自定義表達式模式 4 :自定義符號,下面是前置運算符
prefix operator ~> prefix operator ~>= prefix operator ~< prefix operator ~<= prefix func ~> (_ i: Int) -> ((Int) -> Bool) { { $0 > i } } prefix func ~>= (_ i: Int) -> ((Int) -> Bool) { { $0 >= i } } prefix func ~< (_ i: Int) -> ((Int) -> Bool) { { $0 < i } } prefix func ~<= (_ i: Int) -> ((Int) -> Bool) { { $0 <= i } } extension Int { static func ~= (pattern: (Int) -> Bool, value: Int) -> Bool { pattern(value) } } var age = 9 switch age { case ~>=0: print("1") case ~>10: print("2") default: break }
-
-
2.10、可以使用
where
為模式匹配增加匹配條件-
(1)、 switch 里面使用
var data = (10, "Jack") switch data { case let (age, _) where age > 10: print(data.1, "age>10") case let (age, _) where age > 0: print(data.1, "age>0") default: break }
-
(2)、 for in 里面使用
var ages = [10, 20, 44, 23, 55] for age in ages where age > 30 { print(age) // 44 55 }
-
(3)、 協議中關聯類型里面使用
protocol Stackable { associatedtype Element } protocol Container { associatedtype Stack : Stackable where Stack.Element : Equatable }
-
(4)、 函數里面使用
func equal<S1: Stackable, S2: Stackable>(_ s1: S1, _ s2: S2) -> Bool where S1.Element == S2.Element, S1.Element : Hashable { return false }
-
(5)、 擴展里面使用
extension Container where Self.Stack.Element : Hashable { }
-