十三. 类的构造函数
1. 构造函数的介绍
- 构造函数类似于OC中的初始化方法:init方法
- 默认情况下载创建一个类时,必然会调用一个构造函数
- 即便是没有编写任何构造函数,编译器也会提供一个默认的构造函数。
- 如果是继承自NSObject,可以对父类的构造函数进行重写
2.构造函数的基本使用
2.1 构造函数的基本使用
- 类的属性必须有值
- 如果不是在定义时初始化值,可以在构造函数中赋值
class Person: NSObject var name : String var age : Int // 重写了NSObject(父类)的构造方法 override init() name = "" age = 0 } } // 创建一个Person对象 let p = Person()
2.2 初始化时给属性赋值
- 很多时候,我们在创建一个对象时就会给属性赋值
- 可以自定义构造函数
- 注意:如果自定义了构造函数,会覆盖init()方法.即不在有默认的构造函数
class Person: NSObject var name : String var age : Int // 自定义构造函数,会覆盖init()函数 init(name : String, age : Int) self.name = name self.age = age } } // 创建一个Person对象 let p = Person(name: "ryan", age: 18)
2.3 字典转模型(初始化时传入字典)
- 真实创建对象时,更多的是将字典转成模型
- 注意:
- 去字典中取出的是NSObject,任意类型.
- 可以通过as!转成需要的类型,再赋值(不可以直接赋值)
class Person: NSObject var name : String var age : Int // 自定义构造函数,会覆盖init()函数 init(dict : String : NSObject) name = dict"name" as! String age = dict"age" as! Int } } // 创建一个Person对象 let dict = "name" : "ryan", "age" : 18 let p = Person(dict: dict)
2.4 字典转模型(利用KVC转化)
- 利用KVC字典转模型会更加方便
- 注意:
- KVC并不能保证会给所有的属性赋值
- 因此属性需要有默认值
- 基本数据类型默认值设置为0
- 对象或者结构体类型定义为可选类型即可(可选类型没有赋值前为nil)
class Person: NSObject // 结构体或者类的类型,必须是可选类型.因为不能保证一定会赋值 var name : String? // 基本数据类型不能是可选类型,否则KVC无法转化 var age : Int = 0 // 自定义构造函数,会覆盖init()函数 init(dict : String : NSObject) // 必须先初始化对象 super.init() // 调用对象的KVC方法字典转模型 setValuesForKeysWithDictionary(dict) } } // 创建一个Person对象 let dict = "name" : "ryan", "age" : 18 let p = Person(dict: dict)
十四. 闭包
1. 闭包的介绍
- 闭包和OC中的block非常相似
- OC中的block是匿名的函数
- Swift中的闭包是一个特殊的函数
- block和闭包都经常用于回调
2. 闭包的使用
2.1 block的用法回顾
- 定义网络请求的类
@interface HttpTool : NSObject - (void)loadRequest:(void (^)())callBackBlock; @end @implementation HttpTool - (void)loadRequest:(void (^)())callBackBlock { dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSLog(@"加载网络数据:%@", [NSThread currentThread]); dispatch_async(dispatch_get_main_queue(), ^{ callBackBlock(); }); }); } @end
- 进行网络请求,请求到数据后利用block进行回调
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self.httpTool loadRequest:^{ NSLog(@"主线程中,将数据回调.%@", [NSThread currentThread]); }]; }
- block写法总结:
block的写法: 类型: 返回值(^block的名称)(block的参数) 值: ^(参数列表) { // 执行的代码 };
2.2使用闭包代替block
- 定义网络请求的类
class HttpTool: NSObject { func loadRequest(callBack : ()->()){ dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in print("加载数据", [NSThread.currentThread()]) dispatch_async(dispatch_get_main_queue(), { () -> Void in callBack() }) } } }
- 进行网络请求,请求到数据后利用闭包进行回调
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { // 网络请求 httpTool.loadRequest ({ () -> () in print("回到主线程", NSThread.currentThread()); }) }
2.3 闭包写法总结:
2.3.1闭包的写法:
类型:(形参列表)->(返回值) 技巧:初学者定义闭包类型,直接写()->().再填充参数和返回值 值: { (形参) -> 返回值类型 in // 执行代码 }
2.3.2闭包的简写
- 如果闭包没有参数,没有返回值.in和in之前的内容可以省略
httpTool.loadRequest({ print("回到主线程", NSThread.currentThread()); })
- 尾随闭包写法:
- 如果闭包是函数的最后一个参数,则可以将闭包写早()后面
- 如果函数只有一个参数,并且这个参数是闭包,那么()可以不写
httpTool.loadRequest() { print("回到主线程", NSThread.currentThread()); } // 开发中建议该写法 httpTool.loadRequest { print("回到主线程", NSThread.currentThread()); }
2.3.3 闭包的循环引用
- 如果在HttpTool中有对闭包进行强引用,则会形成循环引用
class HttpTool: NSObject { // 定义属性,来强引用传入的闭包 var callBack : (()->())? func loadRequest(callBack : ()->()){ dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in print("加载数据", [NSThread.currentThread()]) dispatch_async(dispatch_get_main_queue(), { () -> Void in callBack() }) } self.callBack = callBack } }
- swift中解决循环引用的方式
// weak var weakSelf = self; // [weak self] () -> () in // [unowned self] () -> () in httpTool.loadRequest { [unowned self] () -> () in self.view.backgroundColor = UIColor.redColor() print("回到主线程", NSThread.currentThread()); }
十五 懒加载
1. 懒加载的介绍
- swift中也有懒加载的方式
- (苹果的设计思想:希望所有的对象在使用时才真正加载到内存中)
- 和OC不同的是swift有专门的关键字来实现懒加载
- lazy关键字可以用于定义某一个属性懒加载
2. 懒加载的使用
- 格式
lazy var 变量: 类型 = { 创建变量代码 }()
- 懒加载的使用
// 懒加载的本质是,在第一次使用的时候执行闭包,将闭包的返回值赋值给属性 // lazy的作用是只会赋值一次 lazy var array : [String] = { () -> [String] in return ["ryan", "szy", "jack"] }()
时间: 2024-10-08 04:26:59