您的当前位置:首页正文

逃逸闭包&非逃逸闭包

来源:华拓网

逃逸闭包&非逃逸闭包

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()
    }