Swift学习笔记之流程控制

Swift学习笔记

根据《Swift编程权威指南》和 Swift官方文档 学习整理的Swift学习笔记,持续更新,中间有什么错误,欢迎大家留言讨论。

系列总目录

官方文档

swift官方文档

二、流程控制

1、条件语句 if - else

1.1 if/else

​ 后面所跟条件必须是Bool类型。

var population: Int = 5422 
var message: String
if population < 10000 {
		message = "\(population) is a small town!"
} else {
		message = "\(population) is pretty big!"
}
print(message)

Swift 的比较运算符

比较运算符含义
<计算左边的值是否小于右边的值
<=计算左边的值是否小于等于右边的值
>计算左边的值是否大于右边的值
>=计算左边的值是否大于等于右边的值
==计算左边的值是否等于右边的值
!=计算左边的值是否不等于右边的值
===计算两个实例是否指向同一个引用
!==计算两个实例是否不指向同一个引用

Swift的逻辑运算符

逻辑运算符含义
&&逻辑与:当且仅当两者都为真时结果为真(否则结果为假)
||逻辑或:两者任意之一为真时结果为真(只有两者都为假时结果为假)
!逻辑非:真变为假,假变为真
var b: Bool = true
if !b{
	print("!b:\(!b)")
}

1.2 三目运算符(类似于Java)

var a = 11
var message = a > 10 ? "a大于10" : "a小于等于10"

1.3 else if

var score = 85
if score >= 85 {
  print("A")
} else if score >= 75 && score < 85 {
  print("B")
} else if score >= 60 && score < 75 {
  print("C")
} else {
  print("D")
}

2、switch 语句

2.1 最基本的switch语句

var statusCode: Int = 404
var errorString: String
switch statusCode {
case 400:
		errorString = "Bad request"
case 401:
		errorString = "Unauthorized"
case 403:
		errorString = "Forbidden"
case 404:
		errorString = "Not found"
default:
		errorString = "None"
}

​ 在Swift中每个case分支默认有break。并且每个分支后必须至少跟一句语句。

switch支持枚举类型,Character,String

2.2 switch 分支可以有多个值

var statusCode: Int = 404
var errorString: String
switch statusCode {
case 400, 401, 403, 404:
  	errorString = "400, 401, 403, 404"
  	fallthrough	 		// 状态转移语句,贯穿效果
default:
  	errorString = "Please review the request and try again."
}

2.3 fallthrough

​ 上面的代码中还添加了名为 fallthrough 的状态转移语句(control transfer statement)。状态转移语句能让你修改某个控制流中的代码执行顺序。这类语句能把控制权从一块代码转移到另一 块代码。

​ 在这里,fallthrough告诉switch语句从一个分支的底部”漏(fall through)“到下一个分支去。如果某个匹配上的分支末尾有fallthrough控制转移语句,它会先执行自己的代码,再把控制权转移到下面紧挨着的分支。

​ 这里可以看做是其他语言的switch - case 不加 break语句。Swift的switch-case每个分支默认就有break语句的效果。

2.4 区间

var statusCode :Int = 410
var errorString: String
switch statusCode {
case 401,402:
    errorString = "401、402"
case 404:
    errorString = "Not found"
case 405...410:
    errorString = "405—410"
default:
    errorString = "Please review the request and try again."
}

​ 上述代码中的 405—410 是 包包含了405、410以及中间所有整数的区间。

2.5 值绑定

​ 假设无论程序能否识别状态码,都需要把实际的状态码放进errorString,那么可以利用 Swift的值绑定(value binding)特性在前面switch语句的基础上做到这一点。

​ 值绑定能在某个特定分支中把待匹配的值绑定(bind)到本地的常量或变量上。这个常亮或者变量只能在该分支中使用。

var statusCode :Int = 420
var errorString: String
switch statusCode {
case 404:
    errorString = "\(statusCode):Not found"
case 401,402:
    errorString = "\(statusCode):401或者402"
case 405...410:
    errorString = "\(statusCode):405—410"
//    值绑定
case let unknowCode:
    errorString = "\(unknowCode):is not a known error code."
print(errorString)

​ 上述代码中,用了字符串插值来把statusCode传入每个分支的errorString。当statusCode没有匹配上面的任何一个分支时,我们创建了一 个临时常量unknownCode,将其绑定为statusCode的值。

​ 注意这里用了常量,所以unknownCode的值是固定的。如果因为某些原因需要对unknownCode 做些处理,就可以用var而不是let来声明。举例来讲,这么做可以在最后一个分支体中修改 unknownCode的值。

​ 这里只是展示了值绑定的语法,但是其实没什么作用。标准的default分支就能得到同样的结果。 把最后一个分支替换为default分支,如以下代码所示。

var statusCode :Int = 420
var errorString: String
switch statusCode {
case 404:
    errorString = "\(statusCode):Not found"
case 401,402:
    errorString = "\(statusCode):401或者402"
case 405...410:
    errorString = "\(statusCode):405—410"
default:
    errorString = "\(statusCode):is not a known error code."
print(errorString)

2.6 where 子句

// 用where创建筛选条件
var statusCode = 204
var errorString: String
switch statusCode{
case 100,101:
    errorString = "Informational, \(statusCode)."
case 204:
    errorString = "success but not content,204"
case 300...307:
    errorString = "300—307:\(statusCode)"
case 500...505:
    errorString = "500—505:\(statusCode)"
case let unknownCode where (unknownCode >= 200 && unknownCode < 300)
        || unknownCode > 505:
    errorString = "\(unknownCode) is not known error code"
default:
    errorString = "Unexpected error encountered."
}
print(errorString)

​ 只要不用Swift的fallthrough特性,switch语句就会在找到一个匹配分支并执行分支体代码后马上停止执行。当statusCode等于204时,switch会匹配第二个分支并将errorString设置 为相应的值。所以,即使204处于where子句制定的区间内,switch语句也不会执行那个子句。

2.7 元组和模式匹配

​ 有了statusCode和errorString后,把这两块信息拼拼接起来就很有用了。尽管两者逻辑相关,但是目前是存储在两个独立变量中的。元组(tuple)可以用来组合这两个变量。

元组:

  • 开发者认为具有逻辑关联的两个或多个值的有限组合。
  • 不同的值被组合为单个复合。
  • 组合的结果是一个元素的有序列表。
2.7.1 使用元组

​ 创建一个元组来组合statusCode和errorString,如以下代码所示。

let error = (statusCode, errorString)

​ 元组的元素可以用下标访问,如以下代码所示。

print(error.0)
print(error.1)

​ 执行代码,将得到error.0(元组的第一个元素)和error.1(元组的第二个元素)分别是是418和"Unexpected error encountered."。

2.7.2 给元组的元素起名

​ Swift的元组也可以保存命名元素。元组的命名元素能使代码更可读。

let errorN = (code:statusCode, error:message)
print(errorN.code)
2.7.3 用元组做模式匹配
let firstErrorCode = 404
let secondErrorCode = 200
let errorCode = (firstErrorCode,secondErrorCode)

switch errorCode{
case (404,404):
    print("No itemes found.")
case (404,_):       // “_”匹配任意值的通配符
    print("First item not found.")
case(_,404):
    print("Second item not found.")
default:
    print("All item found.")
}

​ 第二个分支和第三个分支的下划线“_”是能匹配任意值的通配符,这样能使这两个分支专注于某个特定请求的错误码。

2.8 switch 与 if/else

2.8.1 if-case语句替换单个分支的switch

​ 先看如下代码:

let age = 25 
switch age { 
case 16...30:
		print("青年人") 
default:
		break 
}

​ 这里只是为了匹配出18-30岁的青年人,但是必须有default分支;switch语句必须被全覆盖。

​ swift提供了更好的方法实现这种逻辑。以上代码可修改为:

let age = 25
if case 16...30 = age{
    print("青年人") 
}

​ 以上代码简化了switch,只需要检查age是否在给定区间。不再需要写没有实际用处的default分支。

2.8.2 带多个条件的if-case语句

​ 以下代码和2.6.1处代码的功能一样,但是多了些新的条件,逗号后面的代码会检查age是否大于等于18。

if case 16...30 = age , age>=18{
    print("成年人")
}

※ 区间类型

let range1: ClosedRange<Int> = 1...5 
let range2: Range<Int> = 1..<4
let range3: PartialRangeThrough<Int> = ...5

print(range3.contains(-1))		// true

print(range1.contains(2))		// false

1…5 :是闭区间运算a...b,a <= 取值 <= b

1…<4 :是半开区间运算a..<b,a <= 取值 < b

…5 :是单侧区间:让区间朝一个方向尽可能的远(使用详见数组)

range.contains(x) 方法:返回该值是否在此范围。

​ 字符、字符串也能使用区间运算符,但是默认不能用在for-in中。

let stringRange1 = "a"..."f"  // ClosedRange<String>
stringRange1.contains("b")     // false
stringRange1.contains("d")     // true
stringRange1.contains("g")     // false
let stringRange2 = "cc"..."ff"  // ClosedRange<String>
stringRange2.contains("cb")     // false
stringRange2.contains("cd")     // true
stringRange2.contains("fg")     // false

3、循环

3.1 for-in 循环

3.1.1 for-in循环
// for - in 循环
var myFirstInt: Int = 0
for i in 1...5 {
    myFirstInt += 1
  	i = i+1 		// 报错:i 是常量
    print("myFristInt equals \(myFirstInt) at iteration \(i)")
}

​ for关键字意味着这是个循环。接着声明了一个迭代器(interator)i,用来表示循环的当前重复次数。迭代器只是在循环体内存在常量(意味着我们不能在循环体内修改 i 的值),编译器会帮你管理这个常量。

​ 当然,我们可以给它手动声明为var

var myFirstInt: Int = 0
for var i in 1...5 {
    myFirstInt += 1
  	i = i+1
    print("myFristInt equals \(myFirstInt) at iteration \(i)")
}

​ 如果 i 用不到,可以使用下划线 _ 代替

for _ in 1...5 {
    myFirstInt += 1
    print(myFirstInt)
}
3.1.2 带where子句的for-in循环

​ 下面代码的功能是打印1到50之间3的倍数。

for i in 1...50 where i % 3 == 0 {
    print(i)
}

​ 假如没有where子句,以上代码等同于如下代码

for i in 1...50 {
    if i % 3 == 0 {
        print(i)
    }
}
3.1.3 类型推断概述

​ 观察3.1.1和3.1.2的代码。这里并没有把i声明为Int类型。它本应为:

var myFirstInt: Int = 0
for i:Int in 1...5 {
    myFirstInt += 1
    print("myFristInt equals \(myFirstInt) at iteration \(i)")
}

​ 但是Int类型并没有显示声明出来,i的类型可以用上下文推断出来。

3.2 while循环

​ 只要条件为真,while循环会一直执行体内的循环。

​ 3.1.1处代码等同于:

var i = 1
var myFirstInt: Int = 0
while i < 6 {
    myFirstInt += 1
    print(myFirstInt)
    i += 1
}

3.3 repeat-while 循环

就是其他语言的do-while循环

​ while循环和repeat-while循环的区别在于何时计算条件。while循环在进入循环之前计算条件,意味着while循环体永远不会执行。repeat-while循环则一定会循环一次。

repeat{
    myFirstInt += 1
    print(myFirstInt)
    i += 1
} while i < 6

3.4 控制转移语句

3.4.1 continue

continue用于跳出本次循环。以下代码用于,打印11—20,不打印15。

var index = 10
repeat{
   index = index + 1
   if( index == 15 ){ 	// index 等于 15 时跳过
      continue
   }
   print( "index 的值为 \(index)")
} while index < 20
3.4.2 break

break用于退出循环。

​ 以下代码用于判断index是否位于1-100之中,如果命中目标,可提前结束循环。

var i = 1
var index = 16
var b = false
repeat {
    if i == index{
        b = true
      	break		// 命中目标,结束循环
    }
    i += 1
} while i < 100
print(b)

二、2.3 fallthrough也是控制转移语句

3.5 标签语句

​ 在循环语句或switch语句前面加上标签,它由标签名和紧随其后的冒号(:)组成。在breakcontinue后面跟上标签名可以显式地在循环语句或switch语句中更改控制流,把控制权传递给指定标签标记的语句。

​ 标签的作用域是该标签所标记的语句之后的所有语句。可以不使用带标签的语句,但只要使用它,标签名就必唯一。

outer: for i in 1...4 {
    for k in 1...4 {
        if k == 3 {
            continue outer
        }
        if i == 3 {
            break outer
        }
        print("i == \(i), k == \(k)")
    }
}

​ 上述代码,如果没有标签,那么continue和break默认控制的是内层for循环,通过标签可以达到控制外层循环的作用。

下一章 容器(集合)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值