一、流程控制
- 1.1、if 语句
let age = 5 if age > 10 { print("\(age) 大于 10 ") } else if age > 3 { print("\(age) 大于 3 ") } else { print("\(age) 小于 3 ") }
提示:
- if 后面的条件可以省略小括号,而条件后面的
花括号
不可以省略- if 后面的类型只能是 bool 类型
- 1.2、while 语句(先判断后执行)
var num = 5 while num > 0 { num -= 1 print("num=\(num)") }
- 打印结果:num=4、num=3、num=2、num=1、num=0
- 1.3、repeat while 语句(先执行后判断)
var num = -1 repeat{ print("num=\(num)") }while num > 0
- 打印结果:num=-1,
提示:repeat-while 相当于 OC 里面的 do-while
- 1.4、for 语句
- 闭区间运算符:
a...b
;a<= 取值 <=b
let names = ["小1","小2","小3","小4"] for i in 0...3 { print("name=\(names[i])") }
提示:上面的
0...3
可以替换为let range = 0...3
let a = 0 var b = 3 let names = ["小1","小2","小3","小4"] for i in a...b { print("name=\(names[i])") }
提示:区间可以用常量或者变量来表示的
for _ in 0...3 { print("😆") }
打印了 四次 😆
- for 循环里面的 i 默认是 let,有需要的时候我们可以声明为 var,如下
for var i in 1...3 { i += 2 print("i=\(i)") }
- 打印结果:3、4、5
- 半开区间运算符:
a..<b
;a <= 取值 < b
for i in 1..<3 { print("i=\(i)") }
- 打印结果:1、2
- 1.5、for - 区间运算符用在数组上
- 例一
let names = ["小1","小2","小3","小4"] for name in names[0...3] { print("name=\(name)") }
- 打印结果:小1、小2、小3、小4
- 例二:单侧区间:让区间朝一个方向尽可能的远
let names = ["小1","小2","小3","小4"] for name in names[1...] { print("name=\(name)") }
- 打印结果:小2、小3、小4
let names = ["小1","小2","小3","小4"] for name in names[...2] { print("name=\(name)") }
- 打印结果:小1、小2、小3
let names = ["小1","小2","小3","小4"] for name in names[..<2] { print("name=\(name)") }
- 打印结果:小1、小2
let range = ...5 print(range.contains(8)) print(range.contains(3)) print(range.contains(-1))
- 打印结果:false、true、true
提示: let range = ...5 代表 range的范围从无穷小到 5,包含5
- 1.6、区间类型(重点)
let range1:ClosedRange<Int> = 1...3 let range2:Range<Int> = 1..<3 let range3:PartialRangeThrough<Int> = ...5
- 字符、字符串也能进行区间运算,但默认不能在
for-in
中,因为 ClosedRange:不可数的闭区间
let stringRange1 = "cc"..."ff" // ClosedRange<String> stringRange1.contains("cb") // false stringRange1.contains("dz") // true stringRange1.contains("fg") // false let stringRange2 = "a"..."f" // ClosedRange<String> stringRange2.contains("d") // true stringRange2.contains("n") // false
提示:比较的是ascii,第1位比较第1位,第2位比较第2位,如果第1位大于第1位就没必要比较第二位了,依次类推
0到~
包含了所有可能要用到的 ASCII 字符
let characterRange:ClosedRange<Character> = "\0"..."~" characterRange.contains("b") // true
- 1.8、带间隔的区间值
let hours = 12 let hourInterval = 2 // 从tickMark 的取值:从 4 开始,累加2,不超过 12 for tickMark in stride(from: 4, to: hours, by: hourInterval) { print("tickMark=\(tickMark)") }
- 打印结果:4、6、8、10
- 1.9、switch 语句
- 案例一:switch的基本使用
var num = 10 switch num { case 1: print("值是1") break case 2: print("值是2") break case 3: print("值是3") break default: print("没有匹配") break }
提示:case 和 default 后面不能写大括号
{}
,默认可以不写 break,并不会贯穿到后面的条件
- 案例二:使用 fallthrough 可以实现贯穿效果
var num = 1 switch num { case 1: print("num 值是 1") fallthrough case 2: print("num 值是 2") case 3: print("num 值是 3") default: print("没有匹配") }
- 打印结果:num 值是 1、num 值是 2
- switch使用注意点:
- <1>、switch 必须能保证处理所有的情况
- <2>、case 或者 default 后面至少有一条语句,如果不想有语句可以写 break
var num = 1 switch num { case 1: print("num 值是 1") case 2: break default: print("没有匹配") }
- <3>、如果能保证处理所有的情况,也可以不必使用 default,如下
enum Answer {case right,wrong} let answer = Answer.right switch answer { case Answer.right: print("right") case Answer.wrong: print("wrong") }
提示:上面已经确定 answer 是 Answer 类型,因此可以省略 Answer
enum Answer {case right,wrong} let answer = Answer.right switch answer { case .right: print("right") case .wrong: print("wrong") }
- 复合条件:switch也支持Character、String 类型,如下例子
- 例一:String 类型
let name = "marry" switch name { case "Jack": print("Jack") case "marry": print("marry") default: print("找不到某人") }
- 例二:String 类型
let name = "marry" switch name { case "Jack","marry": print("Jack and marry") default: print("找不到某人") }
- 例三:Character 类型
let character = "A" switch character { case "a","A": print("字母 a或者A") default: print("找不到字母") }
- 匹配区间和元组匹配:
- 匹配区间
let count = 20 switch count { case 0: print("none") case 1..<5: print("a few") case 5..<100: print("several") case 100..<1000: print("hundreds of") default: print("many") }
- 元组匹配
let point = (1,1) switch point { case (0,0): print("the origin") case (_,0): print("on the x-axis") case (0,_): print("on the y-axis") case (-2...2,-2...2): print("inside the box") default: print("many") }
提示:可以使用
_
忽略某个值
- 值绑定:必要时,let 可以改为 var
let point = (2,0) switch point { case (let x,0): print("on the x-axis with an x value of \(x)") case (0,let y): print("on the y-axis with an y value of \(y)") case let (x,y): print("somehere else at (\(x),\(y))") }
- 1.10、where语句
let point = (2,-2) switch point { case let (x,y) where x == y: print("on the line x == y") case let (x,y) where x == -y: print("on the line x == -y") case let (x,y): print("(\(x),\(y)) is just some arbitrary point") }
- 例二:所有的正数相加
let numbers = [-1,2,3,-10,20] var sum = 0 for num in numbers where num > 0 { sum += num } print("最后正数的和=\(sum)")
提示:where 用来过滤 负数
- 1.11、标签语句
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)") } }
二、函数
- 2.1、函数的定义:是一组代码的组合,因此函数也被称为完成特殊功能的代码块。函数三要素:函数名、参数、返回值。
- 有返回值,有参数
func pi()->Double{ return 3.14 } print(pi()) func sum(num1:Int,num2:Int)->Int{ return num1 + num2 } print(sum(num1: 1, num2: 3))
提示:形参默认是 let,也只能是 let
- 无返回值,无参数;下面的几种 无返回值表达的意思是一样的
func sayHello()->Void{ print("Hello") } func sayHello()->(){ print("Hello") } func sayHello(){ print("Hello") }
- 2.2、函数的隐式返回
func sum(num1:Int,num2:Int) -> Int{ num1 + num2 } sum(num1: 1, num2: 3)
提示:如果整个函数的整体是一个单一的表达式,那么函数会隐式返回这个表达式
- 2.3、返回元组 和 实现多值返回
func calculate(v1: Int,v2:Int) -> (sum:Int,difference:Int,average:Int){ let sum = v1 + v2 return (sum,v1-v2,sum>>1) } let result = calculate(v1: 20, v2: 10) result.sum // 和 result.difference // 差 : 10 result.average // 二进制右移 是 平均值 15
提示:
sum>>1
代表值的二进制数 右移 求平均值
- 2.4、函数的文档注释 参考苹果的链接
/// 求和 【概述】 /// /// 将两个整数相加 【更详细的描述】 /// /// - Parameter v1: 第 1 个整数 /// - Parameter v2: 第 2 个整数 /// - Returns : 两个整数的和 /// /// - Note:传入两个整数即可 【批注】,有没有什么特殊的用法 /// func sum(_ v1:Int,_ v2:Int) -> Int{ return v1 + v2 } sum(10, 20)
- 效果如下:
- 2.5、参数标签
- 可以修改参数标签
func goToWork(at time:String){ print("this time is \(time)") } goToWork(at: "08:00")
- 打印结果:
this time is 08:00
- 可以使用下划线
_
省略参数标签
func sum(_ v1:Int,_ v2:Int) -> Int{ return v1 + v2 } sum(10, 20)
- 2.6、默认参数值(Default Parameter Value)
- 参数可以有默认值
func check(name:String = "noPerson",age:Int,job:String = "iOS"){ print("名字=\(name) 年龄=\(age) 工作=\(job)") } check(name: "老大", age: 19, job: "iOS") check(name: "老二", age: 19) check(age: 10, job: "前端") check(age: 16)
提示:只要是有默认参数值的就可以不传参数
- C++的默认参数值有个限制:必须从右往左设置。由于Swift拥有参数标签,因此并没有此类限制
- 但是在省略参数标签时,需要特别注意,避免出错,如下
这里的two
不可以省略参数标签
func test(_ one:Int = 10,two:Int,_ three:Int = 20){ print("打印 one = \(one) two = \(two) three = \(three)") } test(two: 9)
- 2.7、可变参数(Variadic Parameter)
func sum(_ numbers: Int...) -> Int { var total = 0 for i in numbers { total += I } return total } sum(1,2,3)
提示:一个函数 最多只能有1个 可变参数;紧跟在可变参数后面的参数不能省略参数标签,如下
func test(_ numbers:Int...,string:String,_ other:String){ } test(1,2,3, string: "iOS", "Rose")
参数 string 标签不能省略
- 2.8、Swift 自带的 print 函数
/// - Parameters: /// - items: Zero or more items to print. /// - separator: A string to print between each item. The default is a single /// space (`" "`). /// - terminator: The string to print after all items have been printed. The /// default is a newline (`"\n"`). public func print(_ items: Any..., separator: String = " ", terminator: String = "\n")
- 分析: 第一个参数是要打印的值,第二个参数是:连接第一个参数值的 字符,第三个参数是:默认是
\n
换行,如下例子
print(1,2,3,4,5) print(1,2,3, separator: "_") print(1,2,3, separator: "_", terminator: "") print("哈哈")
- 打印结果是: 最后一行不换行,因为
"\n"
被用""
取代了
1 2 3 4 5 1_2_3 1_2_3哈哈
- 2.9、输入输出参数 (In-Out Parameter)
可以用 inout 定义一个输入输出函数:可以在函数内部修改外部实参的值
func swapValues(_ v1:inout Int,_ v2:inout Int){ let tem = v1 v1 = v2 v2 = tem } var num1 = 10 var num2 = 20 swapValues(&num1, &num2) print(num1,num2)
- 打印结果:20 10
- 提示:下面的函数与上面的等价:传进去的是 内存地址,所以可以修改其外部参数的值
func swapValues(_ v1:inout Int,_ v2:inout Int){ (v1,v2) = (v2,v1) }
- 可变参数不能标记为 inout
- 输入输出参数不能有默认值
- 输入输出参数不能传入常量(let)、字面量作为实参。也就是可以被多次赋值的 变量
inout
参数的本质是地址传递 (引用传递)
- 2.10、函数重载 (Function Overload)
规则:函数名相同
参数个数不同 || 参数类型不同 || 参数标签不同
func sum(v1:Int,v2:Int) -> Int{ return v1 + v2 }
- 参数个数不同
func sum(v1:Int,v2:Int,v3:Int) -> Int{ return v1 + v2 }
- 参数类型不同
func sum(v1:Int,v2:Double) -> Double{ return Double(v1) + v2 } func sum(v1:Double,v2:Int) -> Double{ return v1 + Double(v2) }
- 参数标签不同
func sum(_ v1:Int,_ v2:Int) -> Int{ return v1 + v2 } func sum(a:Int,b:Int) -> Int{ return a + b }
- 函数重载注意点一: 返回值类型 与 函数重载 无关
func sum(a:Int,b:Int) -> Int{ return a + b } func sum(a:Int,b:Int) { } sum(a: 1, b: 2)
- 函数重载注意点二:默认参数值和函数重载一起使用产生二义性时,编译器并不会报错(在 C++ 中会报错)
func sum(a:Int,b:Int) -> Int { return a + b } func sum(a:Int,b:Int,c:Int = 10) -> Int { return a + b + c } // 会调用 sum(a:Int,b:Int),这样不太好,还不如编译器报错 sum(a: 1, b: 2)
- 函数重载注意点三:可变参数,省略参数标签,函数重载一起使用产生二义性时,编译器有可能会报错
func sum(a:Int,b:Int) -> Int{ return a + b } func sum(_ a:Int,_ b:Int) -> Int { return a + b } func sum(_ numbers: Int...)->Int{ var total = 0 for i in numbers { total += I } return total }
- 调用
sum(1,2)
报错:Ambiguous use of 'sum'