1 person.dog!.toy!.price = 50 太危险 强制解包,如果没值,直接程序崩溃 2 3 if let dog = person.dog { 4 if let toy = dog.toy { 5 toy.price = 50 6 } 这样解包虽然安全,但是太麻烦 7 }苹果在swift中推荐使用这种方式来给可选链赋值
1 person.dog?.toy?.price = 50 2 //当person.dog 为nil的时候,后面的操作就不再执行4.2 从可选链取值: 从可选链中取出的值得类型一定是可选类型 (有可能取不到)
let price = person.dog?.toy?.price4.3 可选链调用方法:系统会自动判断可选类型是否有值
person.dog?.toy?.flying()三.协议 1.如何定义协议 1.1 swift中协议的方式和类,结构体,枚举相似
protocol SomeProtocol { // 协议方法 }1.2 例如:定义一个运动协议
1 protocol SportProtocol { 2 func playBasketball() 3 func playFootball() 4 }2.声明一个类,并且遵守协议 2.1 声明一个基类(不继承其它类),并遵守协议
1 class SomeClass:FirstProtocol,AnotherProtocol { 2 // 类的内容 3 // 实现协议中的方法 4 } 5 6 例如: 7 class Person : SportProtocol { 8 var name : String = "" 9 10 func playBasketball() { 11 print("打篮球") 12 } 13 14 func playFootball() { 15 print("踢足球") 16 } 17 }2.2 类继承自其他类,并遵守协议
1 class SomeClass:SomeSuperClass, FirstProtocol,AnotherProtocol { 2 // 类的内容 3 // 实现协议中的方法 4 }3.OC swift不支持多继承, 但是可以通过协议,间接实现多继承 4.协议的继承关系 4.1 swift中的及协议和OC(NSObject)中的不同 是:NSObjectProtocol
1 protocol CrazySportProtocol : NSObjectProtocol { 2 func jumping() 3 }4.2 一个协议,可以遵守另一个协议
1 protocol SportProtocol : CrazySportProtocol { 2 func playBasketball() 3 }当一个类遵守了这个协议(SportProtocol) 相当于也遵守了CrazySportProtocol 协议, 所以必须实现这两个协议中的方法 5.协议的可选性 5.1 OC中协议可以定义为可选和必选,默认是必选的 5.2 默认情况下,swift中的协议都是必须实现的 ,否则编译器会报错 5.3 在swift中如何让协议成为可选的(不用必须实现) 要在协议前加 @objc ,可以保留OC某些特性,在方法前加optional 该方法就是可选的了 在实现协议方法时,在方法前面也要加@objc
1 @objc protocol SportProtocol { 2 func playBasketball() 3 func playFootball() 4 //加optional该方法就成为可选的了 5 optional func jumping() 6 } 7 8 class Person: SportProtocol { 9 @objc func playBasketball() { 在方法前也要加上关键字@objc,不管是可选还是必选 10 } 11 @objc func playFootball() { 12 } 13 @objc func jumping() { 14 } 15 }
6.协议在代理模式中的使用 6.1 一般来说协议都用weak来修饰(弱引用) 6.2 weak只能用来修饰类 6.3 在swift中协议既可以被类遵守,也可以被结构体,枚举遵守 6.4 如何让协议只能被类准守 在协议名称后面加上 :class 即可 四.闭包 1.什么是闭包? 闭包和OC中的block非常相似,一般都用来函数的回调 2.block的回顾 block作为属性的格式: `@property (nonatomic, strong) void(^finishedCallback)(NSString *)`; block作为参数的定义格式:` (void (^)(NSString * str))finishedCallback` 3.闭包的格式: (参数列表) -> (返回值类型) 4.闭包的使用
5.尾随闭包
1 // 尾随闭包 : 如果函数的最后一个参数是一个闭包.那么可以将函数调用写成尾随闭包 2 //就是把闭包写到()的后面, 本来是写在()里面的 3 tools?.loadData() { (result) in 4 print("在ViewController中获取到数据:\(result)") 5 } 6 7 // 如果函数有且只有一个参数,并且是一个闭包, 那么()也可以省略 8 tools?.loadData { (result) in 9 print("在ViewController中获取到数据:\(result)") 10 }
6.闭包的循环引用 6.1 一般在定义工具类的时候,会在工具类的方法中用到闭包 6.2 当工具类对闭包有强引用,一个控制器又调用包含该闭包的方法,在闭包方法中使用控制器的属性,就会发生循环引用 6.3 控制器调用方法,就会对工具类有一个强引用, 闭包又拿到控制器的属性,闭包对象就对控制器有一个强引用 6.4 在内存中就相当于这种表现
7.怎么解决闭包的循环引用 与oc中类型,只需要把闭包对控制器的引用改为弱引用 8.怎么改? 当闭包修改控制器的属性时,拿到控制器的属性时,把self(控制器)改成weakself即可 weak var weakself : ViewController? = self 五.swift项目的目录结构简介 1.swift项目目录中没有.h和.m的文件, 只有一个.swift的文件,相当于 2.swift目录中.swift文件就相当于oc中的.h和.m文件 3.在swift中,调用项目中的其他源文件不需要导入头文件 (一个 .swift文件就是一个源文件) 六.懒加载 1.懒加载的介绍 1.1 和OC中不同,swift有专门的关键字实现懒加载 1.2 懒加载本质:当第一次使用时再加载,而且只会被加载一次 2.swift中用lazy关键字来实现懒加载 2.1 懒加载格式
lazy var 变量: 类型 = { 创建变量代码 }()
= 后面是一个闭包 苹果推荐用闭包来实现懒加载,可在闭包中对变量属性进行初始化
2.2 懒加载的使用
1 lazy var names : [String] = { 2 return ["why", "yz", "lmj"] 3 }()
当执行到上面代码的时候,names不会被加载到内存中, 当names第一次使用时,才会被加载
无论names使用多少次,只会被加载一次,也就是说内存中只有一个names属性地址 七.swift中的常见注释 1.单行注释 和OC中的单行注释一样 使用 // 注释内容 2.多行注释 和OC中的多行注释格式一样 /* 注释内容 */ 不同的是,swift中多行注释可以嵌套使用 3.文档注释 与oc中不一样 , swift中 用 /// 注释内容 来实现文档注释 4.分组注释 和oc不一样 oc: #pragma mark - 注释内容 swift: //MARK : - 注释内容 八.访问权限 1.internal :内部的 1.1 当不指定具体的访问权限时,默认为internal 1.2 internal的访问权限: 在当前项目(包)的任何地方都能访问 2.private : 私有的 private的访问权限: 在当前源文件中能够访问 一个 .swift文件就是一个源文件 3.public :公共的 3.1 public的访问权限 : 可以跨包访问 3.2 包的概念: 就是一个项目或一个框架 UIKit也是一个框架 九.异常处理 1.在swift中,如果一个方法的最后有一个throws,那么这个方法能抛出异常 正则表达式就能抛出异常: NSRegularExpression(pattern: <#T##String#>, options: <#T##NSRegularExpressionOptions#>) 2.如果一个方法抛出异常,必须要对异常进行处理,否则编译报错 3.异常处理的三种方式 3.1 try : 手动处理异常,可以拿到异常(error) 要在方法前面加上try 而且外面要用do 包装//try方式 --> 手动处理异常, 并且可以获取到最终的异常结果 do { //如果有异常error有值 let regex = try NSRegularExpression(pattern: "", options: .CaseInsensitive) } catch { //通过error拿到异常结果 print(error) }
3.2 try? : 系统处理异常 try?方式 : 如果有异常,则返回nil,如果没有异常,则返回结果 结果(regex)为可选类型 let regex = try? NSRegularExpression(pattern: "", options: .CaseInsensitive) regex?.matchesInString("", options: [], range: NSMakeRange(0, 0)) 3.3 try! :告诉系统不可能有异常 try!方式(不推荐) 注意:一旦发生异常,程序就会崩溃 let regex = try! NSRegularExpression(pattern: "", options: .CaseInsensitive) 十.如何抛出异常 1.在方法参数的后面加上 throws ,一定要有返回值 2.在某些具体的情况下抛出异常 比如:传的参数不对等等 ,内部要对参数进行判断 3.抛出的异常,一般定义为枚举类型 枚举后面要跟上 ErrorType 这种类型
十一.OC和swift相互调用 1.swift中调用oc 1.1 创建一个桥接文件 (.h的文件) 文件名一般为 Bridge.h 1.2 在桥接文件中导入oc的头文件 1.3 配置桥接文件 工程 —> BuildSetting —> 搜索bridging 在后面写入Bridge.h 的相对路径
2.oc中调用swift 2.1 项目名称要规范 (不能有中文和特殊字符) 2.2 swift中的类,属性,方法名 前面要加 public 2.3 在oc文件中导入 工程名-Swift.h 的头文件 工程名-Swift.h 系统会自动生成