第一部分:

1. Swift简介

  • 2010年的夏天,苹果公司的开发人员Chris Lattne接到了一个特别的任务,为OS X 和iOS平台开发下一代的编程语言,也就是Swift。
  • 苹果公司于2014年WWDC(苹果开发者大会)发布的新开发语言Swift,可与Objective-C共同运行于Mac OS和iOS平台,用于搭建基于苹果平台的应用程序。
  • 2015年的WWDC开发者大会上,苹果公司推出了Swift2.0版本,并且Swfit完全开源。 
  • 自从Swift发布以来,在http://www.tiobe.com中的排行一直处于上升的状态。

2. 变量和常量

 1> 声明变量和常量

  • 在Swift中使用 "let" 修饰一个常量,使用 "var" 修饰一个变量;
  • let修饰常量的值是不可以更改的;
  • var修饰的变量的值是可以更改的;
  • 在声明常量和变量的时候可以使用表情符号、中文等命名常量名和变量名。
  • Swift定义变量或者常量的时候,需要标识出变量或者常量的类型,如果不标识,会根据初始值自动推断。
// MARK: - 定义常量、变量

// 定义常量(使用完第一次就不能修改它的值了)

// MARK: 定义常量变量:类型的隐式转换

let myGender = "男🐲"

print(myGender)

// 定义变量

var carName = "BMW"

carName = "Audi"

print(carName)

// MARK: 定义常量变量:给定类型

let name : String = "Rose" // 如果给定类型,后面的赋值的时候需要根据类型赋值

let age : Int = 18 // 如果定义常量最好给定初始值,定义变量可以不给初始值

var hobby : Int? // ? 表示hobby的类型为可选类型,其值可以为空

print(hobby)

// 定义一个字符类型的变量
var char : Character = "A" // 赋值字符类型的时候,仅需要一个字母即可

// 定义一个bool类型的变量
var flag : Bool = false
  • 值永远不会被隐式转换为其他类型:如果你需要把一个值转换成其他类型,请显式转换
let name = "Angelababy's age is" 
let age = 28
let words = name + String(age)

 2> 字符串

  • String是有序的字符集合,例如“Hello 蓝鸥”
  • Swift中的字符串通过String类型表示,当然也可以看成Character字符类型的集合
  • \(变量名)输出相关内容【插入式取值】
// MARK: - 字符串string

// (1) 创建一个空的字符串
var str_empty = ""
var str_empty1 = String()

// (2) 判断一个字符串为空字符串
if str_empty.isEmpty {
    print("str_empty is empty")
}

// (3) 字符串拼接
var str_url = "http://"
var str = "www.baidu.com"
let str_new_url = str_url + str
print(str_new_url)
print("百度网址:\(str_new_url)") // \(变量名)输出相关内容【插入式取值】

// (4) 获取字符串长度
var str1 = "Hello World"
print("字符串的长度为:\(str1.characters.count)") // 获取字符串的长度

// (5) 字符串的比较
var str2 = "MBBoy"
var str3 = "GBLW"

if str1 != str2 { // ==
    print("两个字符串不相等")
}

3. 数组、字典

 1> 数组

// MARK: - 数组
// Swift中数组中的元素类型必须相同

// 定义一个数组
var nameArray = ["yuanyuan", "GBLW", "WYW"]
print(nameArray)

var nameArray1 : Array<String> = ["YaQian", "XiaoQiang", "FatZhou"]
print(nameArray1)

// 定义一个空数组
let array = Array<String>()

print(array)

// 访问数组的元素
print(nameArray[1])

// 向数组中添加元素
var int_array = Array<Int>()
int_array.append(520)
int_array.append(123)
print(int_array)

// 使用运算符添加数组元素
int_array += [522]
int_array += [528]
print(int_array)

// 使用运算符添加多个数组元素
int_array += [100, 800, 900]
print(int_array)

// 插入元素到具体的位置
int_array.insert(521, atIndex: 1)
print(int_array)

// 移除数组中某个元素
int_array.removeAtIndex(2)
print(int_array)

// 移除所有的元素
int_array.removeAll()
print(int_array)

 2> 字典

// MARK: - 字典

// 定义一个字典类型的变量
var dict : Dictionary<String,Int> = ["a":18, "b":69, "c":38]
print(dict)

// 定义一个空字典
var dict1 :Dictionary<String,Int> = [:]
var dict2 = Dictionary<String,Int>()
print("\(dict1), \(dict2)")

// 向字典添加元素
dict["d"] = 50
print(dict)

// 修改字典中的元素(根据键去修改值)
dict["a"] = 90
print(dict["a"])

// 删除字典中的内容(根据键去删除)
dict.removeValueForKey("b")
print(dict)

4. 元组

 1> 概述

  • 元组是Swift里面独有的一种数据格式。
  • 是一个可以返回多个值的数据格式。
  • 在Swift里面声明的时候使用“()”声明。
  • 元组可以通过下标去访问元素,也可以通过key值去访问元素;
  • 整体的数据结构有点类似于C语言里面的结构体。

 2> 定义一个元组

// 定义一个元组
// 方法一:直接初始化一个元素
let tuples = ("语言", ["iOS", "Java", "html5", "Android"], 12)
print(tuples)

// 方法二:显示初始化
let tuplesNew : (String, Array, Int) = ("语言", ["iOS", "Java", "html5", "Android"], 12)

 3> 取出元组中的值

// 取出元组中的值

// 方式1:直接把元组赋值给另一个常量,根据相关标记进行取值
let tuplesNew1 : (type:String, course:Array, number:Int) = tuplesNew
var info = tuplesNew1.type + tuplesNew1.course[0] + String(tuplesNew1.number)
print(info)

// 方式2:直接根据下标取值
var infoNew = tuplesNew.0 + tuplesNew.1[2] +  String(tuplesNew.2)
print(infoNew)

5. 循环结构

 1> 概述

  Swift里面的循环结构包含:for、for-in、while、repeat-while

 2> 循环

// MARK: - 循环

// 第一种形式:
for var i = 0; i < 10; i++ {
    print(i)
}

// 第二种形式:
for number in 1..<10 { // 开区间(半闭区间),不包括10
    print(number)
}

// 第三种形式:
for number in 1...10 { // 闭区间(全闭区间),包括10
    print(number)
}

// while循环和repeat...while循环
var i = 8
while i > 0 {
    print(i)
    i--
}
repeat {
    
    print("我很好")
    
}while 1 < 0

 3> 遍历数组和字典

// 使用循环遍历数组
var animalArray = ["dog","pig","cat","fish"]

for animal in animalArray {
    print(animal)
}

// 使用循环遍历字典
var animalDict = ["dog":"🐶", "pig":"🐷"]

for (key, value) in animalDict {
    print("\(key) : \(value)")
}

6. 分支结构

 1> if分支结构

// if结构
let flag = true
if flag == true {
    print("haha")
} else {
    print("hehe")
}

 2> switch结构

  在Swift里面,switch的每个case后面会自动的添加一个break,所以不需要手动的去添加了。Swift里面的枚举是可以范围枚举的,系统会根据给定的数据自动的匹配相近的范围 

// switch结构
// 特点一:使用fallthrough实现贯穿每种可能
var value = 0
switch value {
case 0:
    print(0)
    fallthrough
case 1:
    print(1)
    fallthrough
default:
    print("Other")
}
// 特点二:case 后可以使用一个范围
switch value {
case 0...9:
    print("小")
case 9...16:
    print("大")
default:
    print("豹子")
}
// 特点三:case 后可以使用常量和变量
switch value {
case var i where value >= 0 && value < 6: // where 是满足某种条件,可以在分支中进行判断
    i = 99
    print(i)
default:
    print("other")
}
// 特点四:case 后可以匹配一个元组,关键字是元组可以在分支中进行判断
let point = (10, 10)
switch point {
case (10, 0):
    print("case1")
case (10, 8):
    print("case2")
case (_, 10): // "_" 代表忽略
    print("case3")
case (10, 10):
    print("case4")
default:
    print("case5")
}

 注意

  • 不需要添加break关键字,也不会贯穿
  • 添加fallthrough,可以实现贯穿
  • switch要求每个分支必须包含代码

7. 枚举

1> 概述

  • C 语言中,枚举类型将枚举名和一个整型值相对应。
  • Swift 中的枚举更加灵活,不必给每一个枚举成员提供一个确定的值。
  • 如果给枚举成员提供一个值(称为“原始”值),则该值的类型可以是字符串,字符,或是一个整型值或浮点数。

 2> 代码

// MARK: - 枚举(enum)

// 枚举原始类型为Int类型的
enum Direction:Int {
    case east = 0
    case south = 1
    case west = 2
    case north = 3
}
print(Direction.east.rawValue) // rawValue就是找到相对应枚举的原始值

// 枚举原始类型为String类型的
enum Season:String {
    case spring = "春天"
    case summer = "夏天"
    case autumn = "秋天"
    case winnter = "冬天"
}
print(Season.autumn.rawValue)

// 根据原始值获取枚举类型
print(Direction(rawValue: 2))

8. 函数

1> 概述

  • Swift里面用 func 表示声明一个函数。
  • Swift的文件格式里面没有类似于OC的.h文件。所以,如果需要定义一个私有的函数,可以在func前面添加private 修饰。

 2> 函数定义格式

func 函数名(参数名:参数类型,参数名:参数类型....)->返回值类型 {
    函数实现
    return 返回值
  }

 3> 函数类型

  • 无参无返回值
// 1. 无返回值,无参数
func fun1() -> Void {
    print("无返回值,无参数")
}
fun1()
  • 无参有返回值
// 2. 有返回值,无参数
func fun2() -> String {
    return "Swift2.0"
}
print(fun2())
  • 有参无返回值
// 3. 无返回值,有参数
func fun3(name str:String) -> Void {
    print(str)
}
fun3(name: "Swift2.0")
  • 有参有返回值
// 4. 有返回值,有参数
func fun4(num1 a:Int, num2 b:Int) -> Int {
    return a + b
}
print(fun4(num1: 3, num2: 7))
  • 有参多个返回值(返回一个元组)
// 5. 有多个返回值(返回一个元组)
func fun5(num1 a:Int, num2 b:Int) -> (Int, Int, Int) {
    return (a + b, a - b, a * b)
}
print(fun5(num1: 69, num2: 38))

 3> 外部参数和内部参数

  • Swift中,一个参数有两个名字,内部参数名和外部参数名
  • 内部参数名:在函数内部使用的参数名称。
  • 外部参数名:在函数调用时候,显示的参数名称
// 外部参数和内部参数
// name为外部参数,str为内部参数
func fun6(name str:String) -> Void {
    print(str)
}
fun2(name: "Swift2.0")

 4> 忽略外部参数

  • 默认情况下,函数的第一个参数,不显示外部参数名,其余参数,显示外部参数名,并且和内部参数名一致
  • 如果不想要显示外部参数名,可以使用“_”忽略掉
  • 注意:函数的第一个参数不能使用“_ ”忽略掉外部参数名。
// 忽略外部参数, "_"的作用是忽略外部参数
func fun7(one:Int, _ two:Int) {
    print("忽略外部参数")
}
fun7(8, 9)

 5> inout参数

  inout参数:

   参数默认是用let修饰,即常量

   在参数前面添加var,就可以在函数内部修改参数的值,但不能改变实参变量的值.

   如果参数使用inout来修饰,就成了输入输出参数,在函数内部修改参数,可以影响实参变量的值.

// inout修饰的参数
func test(inout name:String) {
    name = "MBBoy"
    print(name)
}

var myName = "zf"
test(&myName)
print(myName)

// 实参的值不变
func test1(var name:String) {
    name = "MBBoy"
    print(name)
}

var myName1 = "fatzhou"
test1(myName1)
print(myName1)

  运行结果:

Swift语法中怎么判断小数为0 swift语法 简书_可选类型

  

第二部分:

1.可选类型和强制解包(?和!)

 1> 可选类型(?)和强制解包(!)

可选类型(?) 其根源是一个 枚举型,里面有 None 和 Some 两种类型。其实所谓的 nil 就是 Optional.None , 非 nil 就是 Optional.Some.

可选类型是的数据如果不进行解包的话,它是一个 Optional 类型的数据,如果我们想要使用原来类型的数据,必须进行解包

// 定义一个Int类型的可选类型变量
var intNumber:Int? = 8
// 把这个类型类型的变量赋值给另一个可选类型的变量
var intNumberOne:Int? = intNumber
print(intNumberOne)
// 打印出来以后是一个Optional类型的值,如果要取到8,必须对可选类型强制解包!
var intNumberTwo:Int = intNumber!
print(intNumberTwo)

  打印结果:

Swift语法中怎么判断小数为0 swift语法 简书_可选类型_02

 2> 可选绑定

有值和没值,如果可选类型的变量没值时对其强制解包,程序就会崩溃 ,所以,强制解包是非常危险的
   示例代码

// 定义一个Int类型的可选类型变量
var intNumber:Int?

// 把这个类型类型的变量赋值给另一个可选类型的变量
var intNumberOne:Int? = intNumber
print(intNumberOne)

var intNumberTwo:Int = intNumber!
print(intNumberTwo)

   崩溃信息:

Swift语法中怎么判断小数为0 swift语法 简书_可选类型_03

不确定可选类型变量是否有值时,用可选绑定,不需要对可选类型强制解包

var Number:Int?
// ! 表示强制解包
//var NumberOne = Number! // 崩溃
//print(intNumberOne)
// 如果不确定可选类型变量是否有值时,用可选绑定,不需要对可选类型强制解包
if var intNumberTwo = Number {
    print(intNumberTwo)
}

  3> 隐式解析可选类型(!)

有值 和 没值(nil) 两种结果,区别是赋值时,隐式解析可选类型不需要强制解包。

// ! 隐式解析可选类型 : 有值,没值(nil)
var intNum: Int! = 10
// 如果隐式解析可选类型的变量没值,程序一样会崩溃
//var intNumOne = intNum
//print(intNumOne)

// 可选绑定
if var intNumTwo= intNum {
    print(intNumTwo)
}

2.结构体

 1> 概述

添加初始化方法、可以遵守代理协议等
  声明一个结构体的格式:

struct + 结构体的名字 + {
      声明成员变量等
   }

 2> 声明一个结构体代码

1 // 1. 声明一个结构体
 2 struct Rect {
 3     // 1.1 声明结构体变量的属性(存储属性)
 4     var x:Float
 5     var y:Float
 6     var width:Float
 7     var height:Float
 8     
 9     // 1.2 声明结构体属性,要使用static
10     static var desciption:String?
11     
12     // 1.3 声明计算属性(是用来专门计算结构体变量属性的setter和getter方法,其本身并没有存储功能)
13     var centerX:Float {
14         // setter方法
15         set {
16 //            x = newValue
17             x = x / 2
18         }
19         
20         // getter方法,必须要写的方法
21         get {
22             return x / 2
23         }
24     }
25     
26     var centerY:Float {
27         get {
28             return y / 2
29         }
30     }
31     
32     // 1.4 声明方法
33     // 声明一个结构体变量方法(相当于OC中的实例方法)
34     
35     func frameInfor() {
36         print("x:\(x),y:\(y),width:\(width),height:\(height)")
37     }
38     
39     // 声明一个结构体方法(相当于OC中的类方法),使用static修饰
40     static func infor() {
41         print("这是结构体方法")
42     }
43     
44 }
45 
46 // 1. 根据结构体去定义一个结构体变量
47 var frame = Rect(x: 10, y: 10, width: 100, height: 100)
48 
49 // 2. 访问结构体变量中的属性
50 // 注意:结构体变量的属性类型可以使用let去修饰,只不过访问的时候不能对其进行修改
51 print(frame.x)
52 
53 // 3. 访问结构体属性
54 Rect.desciption = "我是结构体属性"
55 print(Rect.desciption)
56 
57 // 4. 访问计算属性
58 frame.centerX = 20 // 这句话就相当于在调用centerX的setter方法
59 
60 let value = frame.centerX // 这句话就相当于在调用centerX的getter方法
61 
62 print(value)
63 print(frame.centerY)
64 
65 // 5. 调用结构体变量方法
66 frame.frameInfor()
67 // 6. 调用结构体方法
68 Rect.infor()

 3> 代码解析

  • 声明一个结构体

相关操作:代码46 - 68行

不需要重写初始化方法,直接可以定义一个结构体变量,代码:46 - 47

  • 声明结构体变量的属性(存储属性)

代码49 - 50行

变量(var),也可以是常量(let),以上代码以var为例

  • 声明结构体属性

声明:代码 9 - 10行,访问:代码53 - 55行

要使用 static 修饰,必须由 结构体 进行访问

  • 声明计算属性

代码57 - 63行

专门计算结构体变量属性的 setter 和 getter 方法,其本身并没有存储功能,相当于OC中重写的 setter 和 getter 方法

  • 声明结构体变量方法

代码65 - 66行

实例方法

  • 声明结构体方法

代码67 - 68行

static 修饰,相当于OC中的类方法

注意:类方法中只能使用 类属性,不能使用 对象属性

3.类

 1> 概述

通用且灵活的构造体。我们可以使用与结构体完全相同的语法规则来为类定义属性(常量、变量)和添加方法。

  我们通过关键字class来定义类,并在一对大括号中定义它们的具体内容:

class ClassName {
    类的内部细节
   }

 2> 声明一个父类和子类的代码

1 class Person {
 2     // 1.2 对象属性
 3     var name:String?
 4     var age:Int?
 5     
 6     // 1.3 声明类属性
 7     static var introduce:String?
 8     
 9     // 1.4 计算属性
10     var value:Int {
11         set {
12             age = newValue // 在写计算属性的时候,一定不能出现self,不然会出现死循环
13         }
14         
15         get {
16             return age!
17         }
18     }
19     
20     // 1.1 构造初始化方法
21     init(name:String, age:Int) {
22         self.name = name
23         self.age = age
24     }
25     // 自定义初始化方法
26     init(name:String) {
27         self.name = name
28     }
29     
30     // 1.5 声明一个类方法
31     // 1.5.1 在类方法前面加上一个static修饰【虽然是一个类方法,但是该方法在子类中不能进行重写】
32     static func sayHi() {
33         print(introduce) // 注意:只能使用类属性,不能使用对象属性
34     }
35     // 1.5.2 在类方法前面加上class修饰【它是一个类方法,可以被子类重写】
36     class func sayHello() {
37         print(introduce)
38     }
39     
40     // 1.6 声明一个实例(对象)方法
41     func sayHi1() {
42         print("我是实例方法")
43     }
44 }
45 
46 // 1. 创建对象(注意:要初始化方法)
47 var per : Person = Person(name: "MBBoy", age: 20)
48 
49 // 2. 访问类中的属性
50 // ! 解包后为原有属性(打印结果: MBBoy ),不解包为Optional属性(打印结果 Optional(20) )
51 print(per.name!)
52 print(per.age)
53 
54 // 3. 访问类属性
55 Person.introduce = "我是xxx"
56 
57 // 4. 访问计算属性
58 per.value = 28
59 print(per.value)
60 
61 // 5. 访问类方法
62 Person.sayHello()
63 Person.sayHi()
64 
65 // 6. 访问实例方法
66 per.sayHi1()
67 
68 // 定义一个子类Student,继承Person
69 // Swift不支持多继承
70 class Student:Person {
71     // 重写父类的方法
72     // 重写父类的类方法
73     override class func sayHello() {
74         print("我是子类Student,重写父类的类方法")
75     }
76     
77     // 重写父类的实例方法
78     override func sayHi1() {
79         print("我是子类Student,重写父类的实例方法")
80     }
81 }
82 
83 // 初始化Student对象
84 var stu = Student(name: "张三", age: 25)

代码解析

  • 声明父类

对象的相关操作:46 - 66行

  • 重写初始化方法

代码 20 - 28行,创建对象:代码 46 - 47行

必须重写,不然不能创建对象

  • 声明对象的属性(实例属性)

代码49 - 52行

变量(var),也可以是常量(let),以上代码以var为例

  • 声明类属性

声明:代码 6 - 7行,访问:代码54 - 55行

要使用 static 修饰,必须由 类名 进行访问

  • 声明计算属性

代码57 - 59行

专门计算结构体变量属性的 setter 和 getter 方法,其本身并没有存储功能,相当于OC中重写的 setter 和 getter 方法

self ,不然会出现死循环

  • 计算属性与存储属性

类 或 结构体 里 定义的变量(或常量)。存储属性可以是变量存储属性(用关键字 var定义),也可以是常量存储属性(用关键字let定义)。

计算属性不直接存储值,而是提供一个 getter 和一个可选 的 setter,来间接获取和设置其他属性或变量的值。

  • 声明类方法

代码61 - 63行

注意:类方法中只能使用 类属性,不能使用 对象属性

  两种方式:

class 修饰,它是一个类方法,可以被子类重写 

使用 static 修饰,虽然是一个类方法,但是该方法在子类中不能进行重写

  • 声明实例(对象)方法

代码65 - 66行

相当于OC中的实例方法

  • 声明子类

声明:代码 68 - 81行  

单继承,可以遵循协议,两者同时存在时,先在:后面写父类,后写协议,用逗号隔开

override 关键字

4. 值类型和引用值类型的区别

 值类型

  • 该类型的每个实例持有数据的副本,并且该副本对于每个实例来说是独一无二的一份,比如结构体(struct)、枚举(enum)、元组(tuple)都是值类型
  • 值传递只是单纯的将数据拷贝一份,赋值给一个同类型的变量,两个变量互不影响,一个值发生改变,另一个不会发生任何变化

 引用值类型

  • 该类型的实例共享数据唯一的一份副本(在native层面说的话,就是该类型的每个实例都指向内存中的同一个地址),比如类(class)就是引用类型。
  • 值传递是将一个变量的地址赋值给另一个变量,当一个值发生改变,两个值同时改变
struct animal { // 值类型
    var name:String?
    var age:Int?
    
    init(name:String, age:Int) {
        self.name = name
        self.age = age
    }
}

var dog = animal(name: "贝贝", age: 3)
var dog1 = dog // 此时将dog的数据拷给dog1
dog.name = "欢欢"

print("dog.name:\(dog.name!), dog1.name:\(dog1.name!)")

// 引用值类型
class animal {
    var name:String?
    var age:Int?
    
    init(name:String, age:Int) {
        self.name = name
        self.age = age
    }
}

var dog = animal(name: "贝贝", age: 3)
var dog1 = dog // 此时将dog的数据拷给dog1
dog.name = "欢欢"

print("dog.name:\(dog.name!), dog1.name:\(dog1.name!)")

  打印结果:

 

Swift语法中怎么判断小数为0 swift语法 简书_解包_04

 值类型与引用类型使用情形

  • 使用值类型的情形:       

使用 == 运算符比较实例数据的时候。

你想单独复制一份实例数据的时候。

当在多线程环境下操作数据的时候。

  • 使用引用类型(比如class)的情形:

当使用 === 运算符判断两个对象是否引用同一个对象实例的时候。

当上下文需要创建一个共享的、可变的对象时。

5.协议

 1> 概述

  • 协议定义了一个蓝图,规定了用来实现某一特定工作或者功能所必需的方法和属性
  • 类,结构体或枚举类型都可以遵循协议,并提供具体实现来完成协议定义的方法和功能
  • 任意能够满足协议要求的类型被称为遵循(conform)这个协议

 2> 声明协议

  • @objc 修饰的协议,其中的方法可以声明成可选实现(使用optional修饰)
@objc protocol SayHelloDelegate {
    optional func sayHello()
}
  • 声明一个所有函数都必须实现的协议。
protocol DescriptionDelegate {
    func description() -> String
    static func aClassMethod() ->String//表示声明了一个类方法
}

 3> 遵守协议

直接写在本类名后面的冒号的后面,使用 "," 号分隔

class ErShiXiong: NSObject,SayHelloDelegate, DescripationDelegate {
// 必须实现的协议方法,就必须实现,否则会报错
    func test() {   
    }
// 可选协议方法,会报警告,可以添加 @objc, 或者继承NSObject
    @objc func test1() {
    }
}

6.扩展(Extension)

 1> 概述

extension + 类名(结构体名字)可以对一个类和结构体扩展方法,类似于 OC 的 Category 类目

多次对一个类进行扩展,也可以给一个类扩展协议方法

 2> 使用Extension给类扩充一个方法

extension ErShiXiong {
    func eat() {
        print("吃饭")
    }
}
let er = ErShiXiong()
er.eat()

 3> 给类扩展实现协议

//先声明一个协议MyProtocol
@objc protocol MyProtocol {
    optional func test()   //该法方法可选实现
    func test()
}

extension ErShiXiong: MyProtocol {
    func test() {
              print("Hello")
    }
}

7.闭包

 1> 概述  

  • 闭包是自包含的函数代码块,可以在代码中被传递和使用。 Swift 中的闭包与 C 和 Objective-C 中的 代码块(block)以及其他一些编程语言中的 匿名函数 比较相似。
  • 闭包可以捕获和存储其所在上下文中任意常量和变量的引用。 这就是所谓的闭合并包裹着这些常量和变量,俗称闭包。。

 2> 语法形式

{
   (参数)-> 返回值类型  in 
       执行语句
  }

 3> 闭包的使用(五种方式)

// 声明
var myBlock : ((num1:Int, num2:Int) ->Int)

// 第一种使用方式
myBlock = {
    (num1:Int,num2:Int)->Int in // 切记不能忘记 in
    
    return num1 > num2 ? num1 : num2
}

// 第二种使用方式
myBlock = {
    (num1,num2)->Int in // 切记不能忘记 in
    
    return num1 > num2 ? num1 : num2
}

// 第三种使用方式(常用,见名知意)
myBlock = {
    num1, num2 in
    return num1 > num2 ? num1 : num2
}

// 第四种使用方式
myBlock = {
    num1, num2 in num1 > num2 ? num1 : num2
}

// 第五种使用方式
myBlock = {
    $0 > $1 ? $0 : $1
}

let max = myBlock(num1: 88, num2: 69)
print(max)

 4> 闭包传值(和OC中的Block传值类型)

textField中显示

在第二页声明参数为String,无返回值的闭包变量,用于传值

class SecondViewController: UIViewController {
    // 声明参数为String,无返回值的闭包变量
    var block = {
        (str: String) -> Void in
    }

...

}

在第二页的返回按钮的方法实现闭包

fun buttonAction (){
    // 闭包调用
    self.block!("block返回值")
    self.navigationController?.popViewControllerAnimated(true)
}

在第一页的push按钮中实现闭包

fun pushAction (){
        let secondVC: SecondViewController = SecondViewController()
        secondVC.view.backgroundColor = UIColor.orangeColor()
        // 闭包实现,拿到传回的值
        secondVC.block = {
            (str: String) -> Void in
            self.textField?.text = str
        }
   self.navigationController?.pushViewController(secondVC, animated: true)