9. 函数
- 函数的定义,就是把一些代码封装在一起,有可能有输入,也可能有输出,然后可以被调用执行.
9.1. 无参数, 无返回值的函数
func introduce() {
print("Hello, world!")
}
introduce() // 调用
9.2 有一个参数无返回值的函数
// 参数先写形参名字,再用冒号隔开,写类型名称
func introduce(name:String) {
print("hello, \(name)")
}
introduce(name:"world") // 调用时, 先写入形参名字,再跟:, 最后写入实参
9.3 有返回值的函数
// 有多个参数,则用都好隔开, 返回值,用->进行分开,如果返回的只是一个值,直接跟类型,如果返回的是多个,则需要返回一个元组,
func login(name:String, pwd:String) ->Bool{
if name == "zhangsan" && pwd == "123456" {
return true
}
return false
}
if login(name:"zhangsan", pwd:"111111") {
print("Login Succeed!")
} else {
print("Login Failed!")
}
9.4 有多个返回值的函数
// 多个值返回,返回是一个元组,可以指定名称,也可以不指定名称
func MaxMin(a:Int, b:Int)->(max:Int, min:Int) {
if a > b {
return (a, b)
// return (max:a, min:b)
} else {
return (b, a)
// return (max:b, min:a)
}
}
9.5 参数指定外部使用名称
func MaxMin(FirstValue a:Int, SecondValue b:Int)->(max:Int, min:Int) {
if a > b {
return (a, b)
// return (max:a, min:b)
} else {
return (b, a)
// return (max:b, min:a)
}
}
let (max, mix) = MaxMin(FirstValue:127, SecondValue:126)
9.6 调用时不指定参数名称的函数
func MaxMin(_ a:Int, _ b:Int)->(max:Int, min:Int) {
if a > b {
return (a, b)
// return (max:a, min:b)
} else {
return (b, a)
// return (max:b, min:a)
}
}
let (max, mix) = MaxMin(127, 126)
9.7 参数是不定长的参数
// 参数是不定长, 需要在类型后面添加... 传入的参数可以理解是一个数组.
func CalcSum(_ vals:Int...)->Int {
var sum = 0
for val in vals {
sum += val
}
return sum
}
var sum = CalcSum(1,2,3,4,5,6,7)
print(sum)
9.8 返回值是数组
func RandomArray(count a:Int)->[Int] {
var ret = [Int]()
for _ in 0...a {
ret.append(Int.random(in:0...100))
}
return ret
}
9.9 参数是引用,可以函数内部进行更改
func scale(n: inout Int) {
n *= 10
}
var val:Int = 10
scale(n:&val)
print(val)
10. 枚举类型
定义:
有限状态的集合,如
性别:男,女;
星期:星期一-星期日.
球类: 篮球,足球..
作用:
可以助记
// 性别, 约定,首字母大写.
enum Sex {
case Male,
case Female
}
// 推断定义
let sex = Sex.Male
print(sex, type(of: sex))
// 显示定义
let reqSex:Sex = Sex.Female
print(reqSex, type(of: sex))
// 定义类型,还可以直接一个case.
enum Dir {
case Up, Down, Right, Left
}
let dir = Dir.Up
print(dir, type(of:dir))
dir = .Right // 前面的类型可以省略掉
// 枚举匹配
enum Dir : CaseIterable{
case Up, Down, Right, Left
}
var dir = Dir.Up;
switch dir {
case .Up:
print("上")
case .Down:
print("下")
case .Right:
print("右")
case .Left:
print("左")
}
// 枚举关联值.
enum PlayerState {
case Idle
case Walk(speed:Int)
case Run(speed:Int)
case fly(speed:Int, height:Int)
case die
}
var a1 = PlayerState.Idle
var a2 = PlayerState.Walk(speed: 300) // 关联值
var a3 = PlayerState.fly(speed:300, height:800)
switch a1 {
case .Idle:
print("待机")
case .Walk(let speed):
print("玩家正在以\(speed)行走")
case .Run(let speed):
print("玩家正在以\(speed)奔跑")
case .fly(let speed, let height):
print("玩家正在飞行:\(speed) 高度:\(height)")
case .die:
print("玩家死亡")
}
// 枚举的遍历
enum Dir:CaseIterable {
case Up, Down, Right, Left
}
for dir in Dir.allCases {
print(dir)
}
// 注意: 有关联值的枚举,无法进行遍历.
// 原始值, raw格式.
enum Gender: Int {
case Male = 10
case Female
Case Unknown
}
// 默认没有值.
print(Gender.Male) // male
print(Gender.Male.rawValue) // 10
print(Gender.Female) // female
print(Gender.Female.rawValue) // 11
// 原始值意义,存储一般存储原始值.
// 订单状态
// 已下单,已曲消, 已发货
case OrderState:Int {
case AlreadyOrdered = 0
case AlreadyCancel = 1,
case AlreadyDeliver = 2
}
-
枚举的描述
enum Weather { case Sunny,Cloudy, Rainy, Snowy, Windy // 每一种数据类型,都有descriiption, 这里进行重新定义了一下 var description : String { switch self { case .Sunny: return "晴天" case .Cloudy: return "多云" case .Rainy: return "雨天" case .Snowy: return "下雪" case .Windy: return "大风" } } } print(Weather.Sunny.description) // 晴天
enum Shape { case rectangle(width:Double, height:Double) case circle(radius:Double) var description:Double { switch self { case .circle(let radius): return Double.pi * radius * radius case .rectangle(let width, let height): return width * height } } print(Shape.rectangle(width:20, height:20).description) }
11. 闭包
闭包的本质: 一个匿名函数
// 函数 ()->Void, 因为返回值为,空,所有返回的Void无意义
func hello() {
print("Hello")
}
// 函数调用
hello()
// 匿名函数
let hi = {
print("Hello")
}
// 调用
hi()
有参数: 对于闭包,需要将参数和返回放到匿名函数体.
// 参数放入函数体, 用in隔开
let hi = { (name:String) in
print("Hello, \{name}")
}
// 匿名函数调用,不需要输入函数标签 name.
hi("张三")
有返回值
func sum(a:Int, b:Int) ->Int {
a + b
}
print(sum(a:3, b:4))
// 闭包
let s = {(a:Int, b:Int)->Int in
a + b
}
print(s(3, 8))
func hi()->String {
"Hello, World"
}
let hi2 = { ()->String in
"Hello, World"
}
print(hi2())
闭包可以作为参数传入函数
func sayhi(action:()->Void) {
action()
}
let hi = {
print("你好")
}
// 调用1
sayhi(action:hi) // 你好
// 调用2, 又称尾随闭包
sayhi {
print("hello") // hello.
}
func travel(action:()->Void) {
print("before")
action()
print("after")
}
travel(action:{
print("hello, world")
}) // before, hello, world, after.
// 函数的最后一个参数是闭包函数,可以使用这个写法
travel{
print("hello, world")
} // 输出同上.
func travel(action:(String)->Void) {
print("before")
action("zhengzhou")
print("after")
}
travel{ (place:String) in
print("I travel the \(place) by train")
}
func travel(action:(String, Int)->Void) {
print("before")
action("zhengzhou", 5)
print("after")
}
travel{ (place:String, time:Int) in
print("I travel the \(place) by train at \(time) clock")
}
闭包又返回值
func travel(action:(String, Int)->String) {
print("before")
print(action("zhengzhou", 5))
print("after")
}
travel{ (place:String, time:Int)->String in
return ("I travel the \(place) by train at \(time) clock")
}
参数可以用$0和$1替代,可以进行简写
func travel(action:(String, Int)->String) {
print("before")
print(action("zhengzhou", 5))
print("after")
}
travel{
return ("I travel the \($0) by train at \($1) clock")
}
函数返回值是函数
func travel()->(String)->Void {
return { (place:String) in
print("I want travel to \(place)")
}
}
let r = travel()
r("zhengzhou")
// 下面的函数声明等效于 func read(book:String) -> ()->Void
func read(book:String) -> ()->() {
print("我正在读\(book)")
var count = 0
return {
count += 1
print("第\(count)次读\(book)")
}
}
let a = read("三国演义") //我正在读三国演义
a() //第1次读三国演义
a() //第2次读三国演义
-
闭包在数组中的应用
-
数组的map参数
let datas = [1,2,3,4,5] let n1 = datas.map { item in item * item } print(n1) // [1, 4, 9, 16, 25] let n2 = datas.map { $0 * $0 } print(n2) // [1, 4, 9, 16, 25]
说明: 1. lambda表达式,如果使用自定义参数,则需要用in进行隔开, 如果使用内置的$0,则不需要 2. 如果只有一条语句,则不需要return
-
数组filter使用
let datas = [1,2,3,4,5] let n = datas.filter { $0>2 } print(n) // [3,4,5]
-
数组reduce的使用
reduce 是 Sequence 类型(包括数组)的一个方法,它可以将序列中的所有元素组合成一个单一的输出值。reduce 方法接受一个初始值和一个闭包作为参数,闭包定义了如何将序列中的元素与累积值结合。
let datas = [1,2,3,4,5] let n = datas.reduce(1, { $0 * $1 }) print(n) // 120, = 1*2*3*4*5 let n2 = datas.reduce(0, +) print(n2) // 15 let n3 = datas.reduce(1, *) // 等效于上面的 print(n3) // 120 // 字符串拼接 let words = ["Hello", " ", "world", "!"] // 使用字符串拼接作为闭包 let sentence = words.reduce("", { $0 + $1 }) print(sentence) // 输出:Hello world! // 最后一个参数是闭包,可以将其从括号中拿出来. let sentence2 = words.reduce("") { $0 + $1 } print(sentence2) // 输出:Hello world! // 将内部参数$0,$1改成自定义的名称有意义的参数,更正规 let sentense3 = words.reduce(""){(accumulator, currentWord) in accumulator + currentWord } print(sentense3) // 输出:Hello world!
-
12. 结构体
结构体可以存放多个类型数据,也可以存放函数.
结构体的定义
struct Rectangle {
// 静态名字,需要用static进行定义
static let name = "Rectangle"
var width: Double
var height: Double
var perimeter: Double? = nil
// 可以通过计算属性得到矩形的面积
var area: Double {
return width * height
}
// 计算周长, 由于更改内部属性,需要使用mutating关键字.
mutating func CalcPerimeter() {
self.perimeter = (self.width + self.height) * 2
}
// 初始化方法
init(width: Double, height: Double) {
self.width = width
self.height = height
}
// 结构体方法
func describe() {
print("Rectangle with width \(width) and height \(height)")
}
}
说明:
1. 如果定义init函数,则该用函数为构造函数,如果未定义init函数,则会有默认的init构造函数
2. 如果内部有更改属性的方法(含有mutating), 外部如果要调用,则外部对象不能是let声明.
结构体的使用
// 1. 创建结构体
var rect = Rectangle(width: 10.0, height: 5.0)
// 2. 读取结构体的属性
print(rect.width)
print(rect.area)
// 3. 调用方法
rect.CalcPerimeter()
print(area.perimeter!)