一、闭包的介绍
- 闭包和OC中的block非常相似:
- OC中的block是匿名的函数;
- Swift中的闭包是一个特殊的函数;
- block和闭包都是经常用于回调。
- 注意:闭包和block一样,第一次使用时可能不习惯它的语法
二、闭包的使用
//block的定义
@property(nonatomic,weak) void (^myBlock)();
//block当作参数
-(void)test:(void(^)())block{
block();
}
var block:(形参列表)->(返回值) = {
(形参) -> (返回值类型) in
}
//闭包是特殊的函数
var block:(Int)->() = {
(a:Int) -> () in
print(a + 13)
}
block(3) //16
三、闭包的简写
var block2:()->() = {
() -> () in
print("test")
}
block2() //test
//没有参数和返回值时,就可以省略
var block2 = {
print("test")
}
block2() //test
四、闭包作为参数
var addBlock:(Int,Int)->(Int) = {
(a:Int,b:Int) -> (Int) in
return a + b
}
var multipleBlock:(Int,Int)->(Int) = {
(a:Int,b:Int) -> (Int) in
return a * b
}
func testBlock1(a:Int,b:Int,block:(Int,Int)->(Int)){
let result = block(a, b)
print(result)
}
testBlock1(a: 5, b: 6, block: addBlock) //11
testBlock1(a: 5, b: 6, block: multipleBlock) //30
五、尾随闭包
//尾随闭包
func weisuiBlock(block:()->()){
block()
}
weisuiBlock {
print("尾随闭包")
}
六、闭包的循环引用
- weak:如果这个对象被释放了,那么对应的weakSelf指针指向nil;
//OC中
__weak typeof(self) weakSelf = self
- __unsafe_unretained:如果这个对象被释放了,那么对应的weakSelf指针指向的还是原来的地址,容易导致野指针错误
//OC中
__unsafe_unretained typeof(self) weakSelf = self
- 闭包的循环引用及解决方案一:
//闭包的循环引用及解决方案
class Person{
var block:(()->())?
func test() {
weak var weakSelf = self
block = {
weakSelf
}
}
deinit {
print("释放了")
}
}
var p:Person? = Person()
p?.test()
p = nil //释放了
- 闭包的循环引用及解决方案二
//闭包的循环引用及解决方案二
class Person{
var block:(()->())?
func test() {
block = {
//告诉编译器,里面所有的self都是弱引用
[weak self]
()->() in
self
self
}
}
deinit {
print("释放了")
}
}
var p:Person? = Person()
p?.test()
p = nil //释放了
- 闭包的循环引用及解决方案三
//闭包的循环应用及解决方案三
class Person{
var block:(()->())?
var a:Int = 10
func test() {
//weak:安全,如果对象被释放,值会置为nil(var可选)
//unowned:不安全,如果对象被释放,不会改变里面的值:(let非可选)
unowned let weakSelf = self
block = {
weakSelf.a += 10
weakSelf
weakSelf
}
}
deinit {
print("释放了")
}
}
var p:Person? = Person()
p?.test()
p = nil //释放了
- 闭包的循环使用及解决方案四
//闭包的循环使用及解决方案四
class Person{
var block:(()->())?
var a:Int = 10
func test() {
//weak:安全,如果对象被释放,值会置为nil(var可选)
//unowned:不安全,如果对象被释放,不会改变里面的值:(let非可选)
block = {
[unowned self]
()->() in
self
self
self
}
}
deinit {
print("释放了")
}
}
var p:Person? = Person()
p?.test()
p = nil //释放了
七、闭包在懒加载中的使用
- OC中,懒加载就是重写get方法,并在其中进行一系列初始化操作;
- Swift中,懒加载通过关键字lazy和闭包实现
- 懒加载的两个特性:1.用到时再加载;2.多次使用只加载一次
//懒加载的使用
class Dog{
var age:Int = 8
}
class Owner{
lazy var dog:Dog = Dog()
lazy var dog2:Dog = {
//可以进行一系列的初始化工作
let d = Dog()
d.age = 12
return d
}()
}
let owner = Owner()
owner.dog
owner.dog2
注意:self不可以省略的地方
- 在闭包中使用self时,self不能省略;
- 如果子类有自定义的构造函数或者重写父类的构造函数,此时必须实现父类中使用required修饰的构造函数,在构造函数的super.init()之前,需要保证所有的属性被初始化完毕,此时初始化时候的self不能省略:
class YJWView:UIView{
//定义属性
var titles:[String]
init(frame:CGRect,titles:[String]) {
self.titles = titles
super.init(frame:frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}