流程控制

流程控制的关键字

  • while
  • if
  • guard
  • switch
  • for-in
  • continue
  • break

For-In

1
2
3
4
5
6
let minutes = 60

// 半开区间
for tickMark in 0..<minutes {
    print(tickMark) // 打印从0到59
}

使用stride(from:to:by)实现设置步长的效果,半开区间

使用stride(from:through:by)实现设置步长的效果,全闭区别

1
2
3
4
5
6
7
8
9
let minutesInterval = 5

for tickMark in stride(from: 0, to: minutes, by: minutesInterval){
    print(tickMark) //打印0,5,10...55
}

for tickMark in stride(from: 0, through: minutes, by: minutesInterval){
    print(tickMark) //打印0,5,10...55,60
}

While

white循环有两种形式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// 可能不会执行循环

while condition {
    statements
}

// 至少执行一次循环
repeat {
    statements
} while condition

switch

switch语法如下图所示:

swich synatx

switch中条件的判断必须是详细的,必须考虑到每一种可能存在的情况,不然default语句是不能省略的。如下面的语句加入去掉default语句,在运行的时候会报错。

1
2
3
4
5
6
7
8
switch someCharacter {
case "a":
    print("The first letter of the alphabet")
case "z":
    print("The last letter of the alphabet")
//default:
//    print("Some other charater")
}

默认情况下, swicth语句的case部分不再需要明确指定break, 当多个case语句需要同样的逻辑时,可以使用逗号将case语句区分

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
let caseInSensitiveCharacter = "a"

switch caseInSensitiveCharacter {
case "a", "A":
    print("The first letter of alphabet")
//    break
case "z", "Z":
    print("The last letter of the alphabet")
//    break
default:
    print("Some other charater")
}

case语句同样可以检查是否满足一个区间的匹配

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
let approximateCount = 62
let countedThings = "moons orbiting Saturn"

var naturalCount: String = ""

switch approximateCount {
case 0:
    naturalCount = "no"
case 1..<5:
    naturalCount = "a few"
case 5..<12:
    naturalCount = "several"
case 12..<100:
    naturalCount = "dozens of"
case 100..<1000:
    naturalCount = "hundreds of"
default:
    naturalCount = "many"
}

print("There are \(naturalCount) \(countedThings)")

使用元组,可以在switch语句的case条件中同时比较多个值,下划线_表示匹配任意值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
let somePoint = (1, 1)
switch somePoint {
case (0, 0):
    print("\(somePoint) is at the origin")
case (_, 0):
    print("\(somePoint) is on the x-axis")
case (0, _):
    print("\(somePoint) is on the y-axis")
case (-2...2, -2...2):
    print("\(somePoint) is inside the box")
default:
    print("\(somePoint) is outside the box")
}

当条件匹配多个case语句时,只有第一个匹配的case语句会被执行,上面的例子中, (0, 0)是满足每个条件的,但是只有第一个case语句会执行,后面的都直接被忽略了。

switch语句可以将匹配的case语句赋值到一个临时变量,方便在case语句的代码部分使用.

1
2
3
4
5
6
7
8
9
let anotherPoint = (2,0)
switch anotherPoint {
case (let x, 0):
    print("on the x-axis with an x value \(x)")
case (0, let y):
    print("on the y-axis with an y value \(y)")
case let (x, y):
    print("somewhere else at (\(x), \(y))")
}

switch语句还可以拥有where语句检查额外的条件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
let yetAnotherPoint = (1, -1)

switch yetAnotherPoint {
case let(x, y) where x == y:
    print("(\(x), \(y)) is on the line x=y")
case let(x, y) where x == -y:
    print("(\(x), \(y)) is on the line x=-y")
case let(x, y):
    print("(\(x), \(y)) is just some arbitray")
}

switch语句中,每个满足条件的case语句执行后,就结束了,不像有些语言必须在每个case后面跟上break语句,否则接下来的case语句同样会执行,如果想在switch中实现这种效果,可以使用fallthrough

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
let integerToDescribe = 5
var description = "The number \(integerToDescribe) is"
switch integerToDescribe {
case 2,3,5,7,11,13,17,19:
    description += " a prime number, and also"
    fallthrough
default:
    description += " an integer."
}
print(description) // The number 5 is a prime number, and also an integer.

PS

fallthrough不会检查后面的case语句条件是否满足,会直接执行

带标签的语句语法如下, 在循环语句前设置标签即可

Labeled Statements

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
outter_loop: for i in 1...5 {
    inner_loop: for j in 6...10 {
        if i == 2 && j == 6 {
            continue outter_loop
        }
        else if i == 3 && j == 7 {
                break outter_loop
            }
        else{
            print("\(i), \(j)")
        }
    }
}
// 输出
// 1, 6
// 1, 7
// 1, 8
// 1, 9
// 1, 10
// 3, 6

guard

guard语句和if语句类型,根据条件的真假执行语句,与if不同的是,guard后必须跟else条件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
func greet(person: [String: String]) {
    guard let name = person["name"] else {
        return
    }
    print("Hello \(name)")

    guard let location = person["location"] else {
        print("I hope the weather is nice near you.")
        return
}
    print("I hope the weather is nice in \(location).")
}

greet(person: ["name": "John"])
//Hello John
//I hope the weather is nice near you.

greet(person: ["name": "Jane", "location": "Cupertino"])
//Hello Jane
//I hope the weather is nice in Cupertino.

函数

swift中,函数既可以作为函数的参数,也可以作为返回值存在,函数也可以嵌套函数

默认参数

1
2
3
4
func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {
    // If you omit the second argument when calling this function, then
    // the value of parameterWithDefault is 12 inside the function body.
}

不定参数

在参数类型后面跟...表示这个参数是不定的,它可以结束0个或者多个参数, 一个函数最多一个不定参数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func arithmeticMean(_ numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
arithmeticMean(1, 2, 3, 4, 5)
// returns 3.0, which is the arithmetic mean of these five numbers
arithmeticMean(3, 8.25, 18.75)
// returns 10.0, which is the arithmetic mean of these three numbers

输入输出参数(In-Out参数)

默认情况下,函数的参数都是常量类型,当尝试从函数体内修改参数时,都会报编译错误。如果想修改参数的值,就必须使用In-Out参数,通过在参数名前使用关键字inout。我们只能使用变量作为in-out参数,不能使用常量作为参数,因为常量是不能被修改的。在参数去使用&符号,当传递in-out参数时,in-out参数不能有默认值,可变参数不能被标记为in-out参数。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
var someInt = 3
var anotherInt = 107


func tesetSwapTwoInts(_ a: Int, _ b: Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}
swapTwoInts(someInt, anotherInt) // 会报编译错误


func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and another is now \(anotherInt)")

// someInt is now 107, and another is now 3

函数类型

每个函数都有函数类型,它是由函数参数类型和函数返回值类型构成的

1
2
3
4
5
6
7
func addTwoInts(_ a: Int, _ b: Int) -> Int {
    return a + b
}

func multiplyTwoInts(_ a: Int, _ b: Int) -> Int {
    return a * b
}

上面两个函数类型都是(Int, Int) -> Int

没有参数和返回值的函数类型

1
2
3
func printHelloWorld() {
    print("hello, world")
}

上面的函数类型是() -> Void

使用函数类型

  1. 我们可以像使用普通类型的变量一样使用函数类型。例如,将一个函数赋值为变量

    1
    
    var mathFunction: (Int, Int) -> Int = addTwoInts
  2. 将函数作为参数

    1
    2
    3
    4
    
    func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
        print("Result: \(mathFunction(a, b))")
    }
    printMathResult(addTwoInts, 3, 5)
  3. 将函数作为返回值

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    func stepForward(_ input: Int) -> Int {
        return input + 1
    }
    
    func stepBackward(_ input: Int) -> Int {
        return input - 1
    }
    
    func chooseStepFunction(backward: Bool) -> (Int) -> Int {
        return backward ? stepBackward : stepForward
    }
    
    
    var currentValue = 3
    let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
    
    print("Counting to zero:")
    // Counting to zero:
    while currentValue != 0 {
        print("\(currentValue)... ")
        currentValue = moveNearerToZero(currentValue)
    }
    print("zero!")

函数嵌套

一个函数可以包含另一个函数的定义,或者将嵌套的函数作为返回值返回

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
    func stepForward(_ input: Int) -> Int {
        return input + 1
    }

    func stepBackward(_ input: Int) -> Int {
        return input - 1
    }

    return backward ? stepBackward : stepForward
}

var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)

print("Counting to zero:")
// Counting to zero:
while currentValue != 0 {
    print("\(currentValue)... ")
    currentValue = moveNearerToZero(currentValue)
}
print("zero!")