// MARK:- 事件监听
composeBtn.addTarget(self, action: #selector(MainViewController.composeBtnClick), for: .touchUpInside)
extension BaseViewController {
// 事件监听本质发送消息.但是发送消息是OC的特性
// 将方法包装成@SEL --> 类中查找方法列表 --> 根据@SEL找到imp指针(函数指针) --> 执行函数
// 如果swift中将一个函数声明称private,那么该函数不会被添加到方法列表中
// 如果在private前面加上@objc,那么该方法依然会被添加到方法列表中
// 如果此方法和button的监听 在同一个拓展中,就不用加@objc fileprivate 但是这方法能被其他类调用
@objc fileprivate func composeBtnClick() {
print("composeBtnClick")
}
}
在swift中的初始化
在swift中 在类名的后面跟上()就相当于OC中的 alloc init
Swift中基本运算
Swift中在进行基本运算时必须保证类型一致,否则会出错
相同类型之间才可以进行运算
因为Swift中没有隐式转换
数据类型的转化
Int类型转成Double类型:Double(标识符)
Double类型转成Int类型:Int(标识符)
let a = 10
let b = 3.14
// 错误写法
// let c = a + b
// let c = a * b
// 正确写法
let c = Double(a) + b
逻辑分支
和OC中if语句有一定的区别判断句可以不加() 在Swift的判断句中必须有明确的真假不再有非0即真 必须有明确的Bool值 Bool有两个取值:false/true
let a = 10
// 错误写法:
//if a {
// print("a")
//}
// 正确写法
if a > 9 {
print(a)
}
switch支持区间判断
什么是区间? 通常我们指的是数字区间:0~10,100~200 swift中的区间常见有两种 开区间:0..<10 表示:0~9,不包括10 闭区间:0...10 表示:0~10
定义可选类型
定义一个可选类型有两种写法
最基本的写法
语法糖(常用)
// 错误写法
// let string : String = nil
// 正确写法:
// 注意:name的类型是一个可选类型,但是该可选类型中可以存放字符串.
// 写法一:定义可选类型
let name : Optional = nil
// 写法二:定义可选类型,语法糖(常用)
let name : String? = nil
// 注意:如果可选类型为nil,强制取出其中的值(解包),会出错
引用类型(指针的传递)
默认情况下,函数的参数是值传递.如果想改变外面的变量,则需要传递变量的地址
必须是变量,因为需要在内部改变其值
Swift提供的inout关键字就可以实现
对比下列两个函数
// 函数一:值传递
func swap(var a : Int, var b : Int) {
let temp = a;
a = b;
b = temp
print("a:\(a), b:\(b)"
)}
var a = 10
var b = 20
swap(a, b: b)
print("a:\(a), b:\(b)")
// 函数二:指针的传递
func swap1(inout a : Int, inout b : Int) {
let temp = a
a = b
b = temp
print("a:\(a), b:\(b)")
}
swap1(&a, b: &b)
print("a:\(a), b:\(b)")
定义类的属性
类属性是与类相关联的,而不是与类的实例相关联
所有的类和实例都共有一份类属性.因此在某一处修改之后,该类属性就会被修改
类属性的设置和修改,需要通过类来完成
类属性使用static来修饰
监听属性的改变
在OC中我们可以重写set方法来监听属性的改变
Swift中可以通过属性观察者来监听和响应属性值的变化
通常是监听存储属性和类属性的改变.(对于计算属性,我们不需要定义属性观察者,因为我们可以在计算属性的setter中直接观察并响应这种值的变化)
我们通过设置以下观察方法来定义观察者
willSet:在属性值被存储之前设置。此时新属性值作为一个常量参数被传入。该参数名默认为newValue,我们可以自己定义该参数名
didSet:在新属性值被存储后立即调用。与willSet相同,此时传入的是属性的旧值,默认参数名为oldValue
willSet与didSet只有在属性第一次被设置时才会调用,在初始化时,不会去调用这些监听方法
监听的方式如下:
监听age和name的变化
class Person : NSObject {
var name : String? {
// 可以给newValue自定义名称
willSet (new){ // 属性即将改变,还未改变时会调用的方法
print(name ?? "HF")
print(new ?? "")
}
// 可以给oldValue自定义名称
didSet (old) { // 属性值已经改变了,会调用的方法
print(name ?? "HF")
print(old ?? "old")
}
}
var age : Int = 0
var height : Double = 0.0
}
let p : Person = Person()
// 在赋值时,监听该属性的改变
// 在OC中是通过重写set方法
// 在swift中,可以给属性添加监听器
p.name = "why"
swift中解决循环引用的方式
- 方案一:
- 使用weak,对当前控制器使用弱引用
但是因为self可能有值也可能没有值,因此weakSelf是一个可选类型,在真正使用时可以对其强制解包(该处强制解包没有问题,因为控制器一定存在,否则无法调用所在函数)
- 使用weak,对当前控制器使用弱引用
// 解决方案一:
weak var weakSelf = self
httpTool.loadData {
print("加载数据完成,更新界面:", NSThread.currentThread())
weakSelf!.view.backgroundColor = UIColor.redColor()
}
- //方案二:
- 和方案一类型,只是书写方式更加简单
可以写在闭包中,并且在闭包中用到的self都是弱引用
- 和方案一类型,只是书写方式更加简单
httpTool.loadData {[weak self] () -> () in
print("加载数据完成,更新界面:", NSThread.currentThread())
self!.view.backgroundColor = UIColor.redColor()
}
- 方案三:(不推荐使用)
- 使用关键字unowned
从行为上来说 unowned 更像OC中的 unsafe_unretained
unowned 表示:即使它原来引用的对象被释放了,仍然会保持对被已经释放了的对象的一个 "无效的" 引用,它不能是 Optional 值,也不会被指向 nil
- 使用关键字unowned
httpTool.loadData {[unowned self] () -> () in
print("加载数据完成,更新界面:", NSThread.currentThread())
self.view.backgroundColor = UIColor.redColor()
}