Swift

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

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

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

2> 可选绑定

可选类型分为有值和没值,如果可选类型的变量没值时对其强制解包,程序就会崩溃,所以,强制解包是非常危险的
如果不确定可选类型变量是否有值时,用可选绑定,不需要对可选类型强制解包

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

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

 1 //MARK: - ?和 ! 的区别
 2 // ? 代表可选类型,其实质是一个枚举类型,里边有None和some两种类型,其实所谓的nil值相当于Optional.None,如果有值相当于Optional.Some
 3 // !有值,没值(nil)
 4 
 5 // !强制解包
 6 
 7 var num : Int? = 8
 8 // 如果对没值(nil)的变量进行强制解包的情况下会造成崩溃
 9 var num1 = num!
10 print(num1)
11 
12 // 可选绑定,不用强制解包
13 if var num2 = num {
14     print(num2)
15 }
16 
17 // !隐式解析可选类型:有值,没值(nil)
18 
19 // 如果强制解析没值的变量也会造成崩溃
20 var intNum : Int! = 9
21 var intNum1 = intNum
22 print(intNum1)
23 
24 // 可选绑定
25 if var intNum2 = intNum {
26     print(intNum2)
27 }

2.结构体

1> 概述

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

struct + 结构体的名字 + {

    声明成员变量等

2> 声明一个结构体代码

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

3.类

1> 概述

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

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

  class ClassName { 

      类的内部细节

  }

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

 1 //MARK: - 类(class)
 2 class Person {
 3     var name : String?
 4     var age : Int?
 5     // 构造初始化方法
 6     init(name:String,age:Int){
 7         self.name = name
 8         self.age = age
 9     }
10     // 自定义初始化方式
11     init(name:String) {
12         self.name = name
13     }
14     // 声明类属性
15     static var introduce:String?
16     // 声明计算属性
17     var value:Int {
18         // set方法
19         set(a) {
20             age = a // 在写计算属性的时候一定不能出现self.  否则或造成死循环
21         }
22         get {
23             return age!
24         }
25     }
26     // 声明类方法
27     // 在类方法前边加上static修饰【虽然是一个类方法,但是该方法在子类中不能进行重写】
28     static func sayHi() {
29         print(introduce!)  // 注意:在类方法中只能使用类属性,不能使用对象属性
30     }
31     // 在类方法前边加上class修饰【他是一个类方法,可以被子类重写】
32     class func sayHa() {
33         print(introduce!)
34     }
35     // 声明一个对象(实例)方法
36     func sayHe() {
37         print("hello iam shilipai")
38     }
39 
40 
41 }
42 
43 // 创建对象【此时应该注意和OC区分开,实例对象,:后边跟的是类】(注意:要初始化对象一定要写初始化构造的方法)
44 var person1:Person = Person(name: "MBBoy", age: 38)
45 // 访问类中的属性 (对象属性)
46 print(person1.name!)
47 
48 // 访问类属性
49 Person.introduce = "我是XXXXX"
50 
51 // 访问计算属性
52 person1.value = 28
53 print(person1.value)
54 
55 // 访问类方法
56 Person.sayHi()
57 Person.sayHa()
58 // 访问实例方法
59 person1.sayHe()
60 
61 
62 // 定义一个子类student,继承Person
63 // 在swift中不支持多继承
64 
65 class Student:Person {
66     // 重写父类的方法
67     // 重写父类中的类方法
68     override class func sayHa() {
69         print("重写类的方法")
70     }
71     // 重写父类中的实例方法
72     override func sayHe() {
73         print("重写实例的方法")
74     }
75 }
76 
77 // 初始化student对象
78 var student = Student(name: "小李", age: 18)
79 
80 Student.sayHa()
81 student.sayHe() 

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

 值类型

  • 该类型的每个实例持有数据的副本,并且该副本对于每个实例来说是独一无二的一份,比如结构体(struct)、枚举(enum)、元组(tuple)都是值类型

  • 值传递只是单纯的将数据拷贝一份,赋值给一个同类型的变量,两个变量互不影响,一个值发生改变,另一个不会发生任何变化

 引用值类型

  • 该类型的实例共享数据唯一的一份副本(在native层面说的话,就是该类型的每个实例都指向内存中的同一个地址),比如类(class)就是引用类型。

  • 值传递是将一个变量的地址赋值给另一个变量,当一个值发生改变,两个值同时改变
 1 struct animal { // 值类型
 2     var name:String?
 3     var age:Int?
 4     
 5     init(name:String, age:Int) {
 6         self.name = name
 7         self.age = age
 8     }
 9 }
10 
11 var dog = animal(name: "贝贝", age: 3)
12 var dog1 = dog // 此时将dog的数据拷给dog1
13 dog.name = "欢欢"
14 
15 print("dog.name:(dog.name!), dog1.name:(dog1.name!)")
16 
17 // 引用值类型
18 class animal {
19     var name:String?
20     var age:Int?
21     
22     init(name:String, age:Int) {
23         self.name = name
24         self.age = age
25     }
26 }
27 
28 var dog = animal(name: "贝贝", age: 3)
29 var dog1 = dog // 此时将dog的数据拷给dog1
30 dog.name = "欢欢"
31 
32 print("dog.name:(dog.name!), dog1.name:(dog1.name!)")

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

  • 使用值类型的情形:       

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

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

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

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

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

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

5.协议

 1> 概述

  • 协议定义了一个蓝图,规定了用来实现某一特定工作或者功能所必需的方法和属性

  • 类,结构体或枚举类型都可以遵循协议,并提供具体实现来完成协议定义的方法和功能

  • 任意能够满足协议要求的类型被称为遵循(conform)这个协议

 2> 声明协议

  • @objc 修饰的协议,其中的方法可以声明成可选实现(使用optional修饰)
  • 声明一个所有函数都必须实现的协议。

3> 遵守协议

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

 1 //MARK: - 协议(protocol)
 2 // 当swift中声明协议的时候,协议里有可选方法的时候需要使用 @objc 关键字修饰
 3 @objc protocol MarryDelegate {
 4     func cook()   // 做饭
 5     func wash()   // 洗衣服
 6     optional func hitDouDou()  // 打豆豆
 7 }
 8 
 9 protocol DivorceDelegate {
10     func divisedMoney()  // 分割财产
11 }
12 
13 // 如果一个类要遵循协议的时候如果这个类有父类,要在冒号后先写父类,然后写要遵循的所有协议,用逗号隔开
14 class Man: Person,MarryDelegate,DivorceDelegate {
15     @objc func cook() {
16         print("还好去新东方学了")
17     }
18     @objc func wash() {
19         print("搓衣板派上用场了")
20     }
21     func divisedMoney() {
22         print("分财产")
23     }
24 }
25 
26 // 创建一个男人
27 let man = Man(name: "陈世美", age: 22)
28 man.cook()
29 man.wash()
30 man.divisedMoney()

6.扩展(Extension)

 1> 概述

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

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

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

 3> 给类扩展实现协议

 1 //MARK: - 扩展(Extension)
 2 //扩展协议中的相关方法
 3 extension Man {
 4     @objc func hitDouDou() {
 5         print("打豆豆")
 6     }
 7 }
 8 man.hitDouDou()
 9 
10 // 扩展还可以扩展类的方法(给某个类添加方法,类似于OC中的category类目)以及对象方法
11 extension Man {
12     // 扩展一个对象方法
13     func sing() {
14         print("苍茫的天涯是我的爱")
15     }
16     // 扩展一个类方法
17     class func sleep() {
18         print("早点睡")
19     }
20 }
21 man.sing()
22 Man.sleep()

7.闭包

 1> 概述  

  • 闭包是自包含的函数代码块,可以在代码中被传递和使用。 Swift 中的闭包与 C 和 Objective-C 中的 代码块(block)以及其他一些编程语言中的 匿名函数 比较相似。

  • 闭包可以捕获和存储其所在上下文中任意常量和变量的引用。 这就是所谓的闭合并包裹着这些常量和变量,俗称闭包。。

 2> 语法形式

  {

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

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

 1 //MARK: - 闭包
 2 // 求两个数的最大值
 3 /*
 4 在OC中使用Block实现
 5 int(^myBlock)(int num1,int num2) = ^int(int num1,int num2) {
 6     return num1 > num2 ? num1 : num2;
 7 }
 8 */
 9 // 使用闭包
10 // 最内括号是参数和类型,箭头 指向的是返回值类型
11 var myBlock : ((num1:Int, num2:Int)->Int)
12 // 第一种使用方式
13 myBlock = {
14     (num1:Int,num2:Int)->Int in    // 切记不能忘记in
15     return num1 > num2 ? num1 :num2
16 }
17 
18 // 第二种方式
19 myBlock = {
20     num1,num2 in
21     return num1 > num2 ? num1 : num2
22 }
23 
24 // 第三种方式
25 myBlock = {
26     num1,num2 in
27     num1 > num2 ? num1 : num2
28 }
29 
30 // 第四种方式
31 myBlock = {
32     $0 > $1 ? $0 : $1
33 }
34 
35 // 第五种方式
36 myBlock = {
37     (num1,num2)->Int in
38     return num1 > num2 ? num1 :num2
39 }
40 
41 let max = myBlock(num1: 88, num2: 66)
42 print(max)

注意:在class类中声明变量 最好立刻初始化 或 定义为可选变量,不然该类必须重写初始化方法

原文地址:https://www.cnblogs.com/crazygeek/p/5521533.html