逃逸闭包和自动闭包

1.逃逸闭包

1.当闭包作为一个实际参数传递给一个函数的时候,并且它会在函数返回之后调用,我们就说这个闭包逃逸了.当你声明一个接受闭包作为形式参数的函数时,你可以在形式参数前写@escaping来明确闭包是允许逃逸的;
2.闭包可以逃逸的一种方法是被存储在定义与函数外的变量里.比如说,很多函数接收闭包实际参数来作为启动异步任务的回调.函数在启动任务后返回,但是闭包要直到任务完成–闭包需要逃逸,以便于稍后调用.

        var completionHanglers: [() -> Void] = []
        
        func someFunctionWithEscapingClosure(completionHangler: @escaping () -> Void) {
            
        completionHanglers.append(completionHangler)
        }
        

让闭包@escaping意味着你必须在闭包中显示地引用self

  var completionHanglers: [() -> Void] = []
        
        func someFunctionWithEscapingClosure(completionHangler: @escaping () -> Void) {
            
            completionHanglers.append(completionHangler)
            
        }
        
        
        func someFunctionWithNonecapingClosure(close:() -> Void){
            
            close()
        }
        
        class SomeClass
        {
            var x = 10
            func doSomething()  {
                
                someFunctionWithEscapingClosure {
                    self.x = 100
                }
                
                someFunctionWithNonecapingClosure {
                    x = 200
                }
            }
        }
        
        let instance = SomeClass()
        
        instance.doSomething()
        
        print(instance.x)//200
        
        completionHanglers.first?()
        
        print(instance.x)
        
        

2.自动闭包

1.自动闭包是一种自动创建的用来把作为实际参数传递给函数的表达式打包的闭包.他不接受任何实际参数,并且当它被调用时,它会返回内部打包的表达式的值.
2.这个语法的好处在于通过写普通表达式代替显示闭包而使你省略包围函数形式参数的括号.

 public   func assert(_ condition:@autoclosure () -> Bool,_ message: @autoclosure () -> String = String(), file:StaticString = #file, line: Unit = #line)

let num = 3
  assert(num>3,"num不能大于3")

3.自动闭包允许你延迟处理,因此闭包内部的代码直到你调用他的时候才会运行.对于有副作用或者占用资源的代码来说很用有,因为他可以允许你控制代码何时才进行求值.

        var customersInLine = ["Chris","Alex","Ewa","Barry","Daniella"]
        print(customersInLine.count)//5
        
        let customerProvider = {customersInLine.remove(at: 0)}
        print(customersInLine.count)//5,因为customerProvider没有被调用,所以大括号里面的删除操作并不会执行
        
        print("Now serving \(customerProvider())!")//Now serving Chris! 调用customerProvider方法
        
        print(customersInLine.count)//4

4.当你传一个闭包作为实际参数到函数的时候,你会得到与延迟处理相同的行为.

var customersInLine = ["Chris","Alex","Ewa","Barry","Daniella"]

serve(customer: {customersInLine.remove(at: 0)})

    func serve(customer customerProvider: () -> String)  {
        
        print("Now serving \(customerProvider())!")
    }

5.通过@autoclosure标志标记他的形式参数使用了自动闭包.现在你可以调用函数就像它接收了一个String实际参数而不是闭包.实际参数自动地转换为闭包,因为
customerProvider形式参数的类型被标记为@autoclosure标记.

var customersInLine = ["Chris","Alex","Ewa","Barry","Daniella"]

 serve(customer: customersInLine.remove(at: 0))

    func serve(customer customerProvider:@autoclosure () -> String)  {
        
        print("Now serving \(customerProvider())!")
    }

你可能感兴趣的:(swift,swift,autoclosure,escaping,逃逸闭包,自动闭包)