逃逸闭包&非逃逸闭包
Swift中的闭包有两种:逃逸闭包和非逃逸闭包,前者表示闭包将在函数返回之后执行;而后者则表示在函数返回前,即函数内部执行。
逃逸闭包
- 访问属性或调用方法时必须加
self
- 访问self时需要注意
引用循环
问题 - 闭包在函数
return之后执行
,即异步执行
/*
下面的回调闭包都是逃逸闭包
*/
private lazy var textView: RAPTextView = {
let textView = RAPTextView()
// 文字改变回调
textView.textViewChangedClosure = {
[unowned self]
(textView: UITextView) -> () in
if textView.hasText() {
self.navigationItem.rightBarButtonItem?.enabled = true
} else {
self.navigationItem.rightBarButtonItem?.enabled = false
}
}
// 即将退出第一响应者的回调
textView.beginDragginClosure = {
[unowned self]
(textView: UITextView) -> () in
self.shouldAnimateMenuBar = true
}
textView.font = UIFont.systemFontOfSize(20)
textView.placeholderText = "QWERTYUIOP"
return textView
}()
非逃逸闭包
- 声明函数时,在闭包参数名前加上
@noescape
,告诉编译器这是一个非逃逸闭包
,从而最大限度进行优化,例如:
func doSthSynchronous(@noescape closure: () -> Void) {
// do sth synchronously
}
- 访问属性或方法
不需要使用self
- 不需要担心使用self的引用循环问题?
- 闭包在函数
返回之前执行
,即同步执行
@objc private func textDidChange(noti: NSNotification) {
isFirstTime = false
confirmButton.enabled = searchTextField.text?.characters.count > 0
let sender = noti.object as! UITextField
guard let opText = sender.text else {
return
}
guard let opSchoolArray = KLXSchoolViewModel.sharedViewModel.schoolArray else {
return
}
/*
过滤数组使用的filter方法中的闭包就是一个非逃逸闭包,所以,先过滤数组,再reloadData()
*/
subDataArray = opSchoolArray.filter({ (schoolName) -> Bool in
guard let opRange = schoolName.rangeOfString(opText) else {
return false
}
if opRange.startIndex != opRange.endIndex {
return true
} else {
return false
}
})
tableView.reloadData()
}