在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
1.可选类型和强制解包(?和!)1> 可选类型(?)和强制解包(!)在swift中,可选类型(?) 其根源是一个 枚举型,里面有 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) 打印结果:
2> 可选绑定 可选类型分为有值和没值,如果可选类型的变量没值时对其强制解包,程序就会崩溃 ,所以,强制解包是非常危险的 // 定义一个Int类型的可选类型变量 var intNumber:Int? // 把这个类型类型的变量赋值给另一个可选类型的变量 var intNumberOne:Int? = intNumber print(intNumberOne) var intNumberTwo:Int = intNumber! print(intNumberTwo) 崩溃信息:
如果不确定可选类型变量是否有值时,用可选绑定,不需要对可选类型强制解包 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> 概述 Swift的结构体对比OC来说,可以添加初始化方法、可以遵守代理协议等 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> 代码解析
声明:代码 1 - 44行,定义一个结构体变量和对结构体的相关操作:代码46 - 68行 结构体不需要重写初始化方法,直接可以定义一个结构体变量,代码:46 - 47
声明:代码 3 - 7行,访问:代码49 - 50行 结构体变量的属性可以是变量(var),也可以是常量(let),以上代码以var为例
声明:代码 9 - 10行,访问:代码53 - 55行 要使用 static 修饰,必须由 结构体 进行访问
声明:代码 12 - 30行,访问:代码57 - 63行 用来专门计算结构体变量属性的 setter 和 getter 方法,其本身并没有存储功能,相当于OC中重写的 setter 和 getter 方法
声明:代码 33 - 37行,访问:代码65 - 66行 相当于OC中的实例方法
声明:代码 39 - 42行,访问:代码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) 3> 代码解析
声明:代码 1 - 44行,初始化对象和对对象的相关操作:46 - 66行
重写:代码 20 - 28行,创建对象:代码 46 - 47行 与结构体不同,类的初始化方法必须重写,不然不能创建对象
声明:代码 2 - 4行,访问:代码49 - 52行 对象的属性可以是变量(var),也可以是常量(let),以上代码以var为例
声明:代码 6 - 7行,访问:代码54 - 55行 要使用 static 修饰,必须由 类名 进行访问
声明:代码 9 - 18行,访问:代码57 - 59行 用来专门计算结构体变量属性的 setter 和 getter 方法,其本身并没有存储功能,相当于OC中重写的 setter 和 getter 方法 在写计算属性的时候,一定不能出现 self ,不然会出现死循环
· 存储属性就是 类 或 结构体 里 定义的变量(或常量)。存储属性可以是变量存储属性(用关键字 var定义),也可以是常量存储属性(用关键字let定义)。 · 除存储属性外,类、结构体和枚举可以定义计算属性。计算属性不直接存储值,而是提供一个 getter 和一个可选 的 setter,来间接获取和设置其他属性或变量的值。
声明:代码 30 - 38行,访问:代码61 - 63行 注意:类方法中只能使用 类属性,不能使用 对象属性 两种方式: 使用 class 修饰,它是一个类方法,可以被子类重写 使用 static 修饰,虽然是一个类方法,但是该方法在子类中不能进行重写
声明:代码 40 - 43行,访问:代码65 - 66行 相当于OC中的实例方法
声明:代码 68 - 81行 和OC相似,单继承,可以遵循协议,两者同时存在时,先在:后面写父类,后写协议,用逗号隔开 重写父类方法,使用 override 关键字 4. 值类型和引用值类型的区别值类型
引用值类型
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!)") 打印结果:
值类型与引用类型使用情形
使用 == 运算符比较实例数据的时候。 你想单独复制一份实例数据的时候。 当在多线程环境下操作数据的时候。
当使用 === 运算符判断两个对象是否引用同一个对象实例的时候。 当上下文需要创建一个共享的、可变的对象时。 5.协议1> 概述
2> 声明协议
@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 类目 extension 可以多次对一个类进行扩展,也可以给一个类扩展协议方法 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> 概述
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传值类型)需求:创建一个工程,勾选swift语言,创建两个控制器给第一个控制器添加导航控制器,点击按钮push到第二个控制器,在第二个页面添加个按钮,点击返回第一个页面,并将第二页textField中输入的值传到第一页,并在第一页的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) 注意:在class类中声明变量 最好立刻初始化 或 定义为可选变量,不然该类必须重写初始化方法 |
请发表评论