신속한 폐쇄


클로저는 코드에서 사용하거나 값을 매개변수로 전달하는 데 사용할 수 있는 독립적인 기능 코드 블록입니다.

Swift의 클로저는 C 및 Objective-C의 블록은 물론 다른 프로그래밍 언어의 익명 함수와 유사합니다.

전역 함수와 중첩 함수는 실제로 특수 클로저입니다.

클로저 형식은 다음과 같습니다.

전역 함수 중첩 함수 클로저 표현식
이름은 있지만 값을 캡처할 수 없습니다. 이름을 사용하면 닫힌 함수 내에서 값을 캡처할 수도 있습니다. 가벼운 구문을 사용하는 이름 없는 클로저는 컨텍스트에 따라 값을 캡처할 수 있습니다.

Swift의 클로저에는 많은 최적화가 있습니다.

  1. 컨텍스트에 따라 매개변수 및 반환 값 유형을 추론합니다.

  2. 한 줄 표현식 클로저에서 암시적으로 반환합니다(즉, 클로저 본문에는 한 줄의 코드만 있고 생략된 반환)

  3. $0, $1(0부터 시작하여 i번째 매개변수를 나타냄)과 같은 단순화된 매개변수 이름을 사용할 수 있습니다.

  4. 후행 클로저 구문 제공(Trailing closure 구문)

  5. 구문

    다음은 매개변수를 받고 지정된 유형을 반환하는 클로저 구문을 정의합니다.

    {(parameters) -> return type in
       statements
    }

    예제

    import Cocoa
    
    let studname = { print("Swift 闭包实例。") }
    studname()

    위 프로그램 실행 출력은 다음과 같습니다.

    Swift 闭包实例。

    다음 클로저 형식은 두 개의 매개변수를 받고 부울 값을 반환합니다.

    {(Int, Int) -> Bool in
       Statement1
       Statement 2
        ---
       Statement n
    }

    예제

    import Cocoa
    
    let divide = {(val1: Int, val2: Int) -> Int in 
       return val1 / val2 
    }
    let result = divide(200, 20)
    print (result)

    위 프로그램의 실행 출력은 다음과 같습니다.

    10

    클로저 표현식

    클로저 표현식은 간결한 구문을 사용하여 인라인 클로저를 구성하는 방법입니다. 클로저 표현식은 클로저 작성을 간단하고 간단하게 만드는 몇 가지 구문 최적화를 제공합니다.


    sort 함수

    Swift 표준 라이브러리는 정렬을 위해 제공하는 클로저 함수에 따라 알려진 유형의 배열에 있는 값을 정렬하는 sort라는 함수를 제공합니다.

    정렬이 완료된 후 sort(_:) 메서드는 원래 배열과 동일한 크기이고 동일한 유형의 요소를 포함하며 요소가 올바르게 정렬된 새 배열을 반환합니다. sort(_:) 메소드로 수정됩니다.

    sort(_:) 메소드는 두 개의 매개변수를 전달해야 합니다:

    • 알려진 유형의 배열

    • 클로저 함수는 배열과 동일한 유형의 두 값을 전달해야 합니다. 요소, 정렬이 완료될 때 전달된 첫 번째 매개변수의 순위가 두 번째 매개변수보다 앞인지 아니면 뒤인지를 나타내는 부울 값을 반환합니다. 첫 번째 매개변수 값이 두 번째 매개변수 값 앞에 나타나면 정렬 폐쇄 함수는 true,反之返回false를 반환해야 합니다.

    import Cocoa
    
    let names = ["AT", "AE", "D", "S", "BE"]
    
    // 使用普通函数(或内嵌函数)提供排序功能,闭包函数类型需为(String, String) -> Bool。
    func backwards(s1: String, s2: String) -> Bool {
        return s1 > s2
    }
    var reversed = names.sort(backwards)
    
    print(reversed)

    위 프로그램 실행의 출력 결과는 다음과 같습니다.

    ["S", "D", "BE", "AT", "AE"]

    첫 번째 문자열(s1)이 두 번째 문자열(s2)보다 큰 경우 역방향 함수는 true를 반환하여 s1이 새 배열에 있어야 합니다. s2 앞에 나타납니다. 문자열에 있는 문자의 경우 "보다 큼"은 "알파벳 순서로 나중에 발생함"을 의미합니다. 이는 문자 "B"가 문자 "A"보다 크고 문자열 "S"가 문자열 "D"보다 크다는 것을 의미합니다. 알파벳 역순으로 정렬되며, "AT"는 "AE" 앞에 정렬됩니다.


    매개변수 이름 약어

    Swift는 인라인 함수에 대한 매개변수 이름 약어 기능을 자동으로 제공합니다. $0, $1, $2를 통해 순차적으로 클로저의 매개변수를 직접 호출할 수 있습니다.

    Example

    import Cocoa
    
    let names = ["AT", "AE", "D", "S", "BE"]
    
    var reversed = names.sort( { 
    ["S", "D", "BE", "AT", "AE"]
     >  } ) print(reversed)

    $0과 $1은 클로저의 첫 번째와 두 번째 문자열 유형 매개변수를 나타냅니다.

    위 프로그램의 실행 출력은 다음과 같습니다.

    import Cocoa
    
    let names = ["AT", "AE", "D", "S", "BE"]
    
    var reversed = names.sort(>)
    print(reversed)

    클로저 표현식에 매개변수 이름 약어를 사용하는 경우 클로저 매개변수 목록에서 해당 정의를 생략할 수 있으며, 매개변수 이름 약어에 해당하는 유형은 다음과 같이 결정됩니다. 함수 유형을 추론합니다. in 키워드는 생략할 수도 있습니다.


    연산자 함수

    위 예에서는 실제로 클로저 표현식을 작성하는 더 짧은 방법이 있습니다.

    Swift의 String 유형은 두 개의 String 유형을 함수 매개변수로 받아들이고 반환하는 보다 큼 기호(>)의 문자열 구현을 정의합니다. Bool 유형의 값입니다. 이는 sort(_:) 메서드의 두 번째 매개변수에 필요한 함수 유형과 일치합니다. 따라서 간단히 보다 큼 기호를 전달하면 Swift는 보다 큼 기호의 문자열 함수 구현을 사용하기를 원한다고 자동으로 추론할 수 있습니다. String类型定义了关于大于号 (>) 的字符串实现,其作为一个函数接受两个String类型的参数并返回Bool类型的值。 而这正好与sort(_:)方法的第二个参数需要的函数类型相符合。 因此,您可以简单地传递一个大于号,Swift可以自动推断出您想使用大于号的字符串函数实现:

    ["S", "D", "BE", "AT", "AE"]

    以上程序执行输出结果为:

    func someFunctionThatTakesAClosure(closure: () -> Void) {
        // 函数体部分
    }
    
    // 以下是不使用尾随闭包进行函数调用
    someFunctionThatTakesAClosure({
        // 闭包主体部分
    })
    
    // 以下是使用尾随闭包进行函数调用
    someFunctionThatTakesAClosure() {
      // 闭包主体部分
    }

    尾随闭包

    尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。

    import Cocoa
    
    let names = ["AT", "AE", "D", "S", "BE"]
    
    //尾随闭包
    var reversed = names.sort() { 
    ["S", "D", "BE", "AT", "AE"]
     >  } print(reversed)

    实例

    reversed = names.sort { 
    func makeIncrementor(forIncrement amount: Int) -> () -> Int {
        var runningTotal = 0
        func incrementor() -> Int {
            runningTotal += amount
            return runningTotal
        }
        return incrementor
    }
     >  }

    sort() 后的 {

    > } 为尾随闭包。

    以上程序执行输出结果为:

    import Cocoa
    
    func makeIncrementor(forIncrement amount: Int) -> () -> Int {
        var runningTotal = 0
        func incrementor() -> Int {
            runningTotal += amount
            return runningTotal
        }
        return incrementor
    }
    
    let incrementByTen = makeIncrementor(forIncrement: 10)
    
    // 返回的值为10
    print(incrementByTen())
    
    // 返回的值为20
    print(incrementByTen())
    
    // 返回的值为30
    print(incrementByTen())

    注意: 如果函数只需要闭包表达式一个参数,当您使用尾随闭包时,您甚至可以把()省略掉。

    10
    20
    30

    捕获值

    闭包可以在其定义的上下文中捕获常量或变量。

    即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。

    Swift最简单的闭包形式是嵌套函数,也就是定义在其他函数的函数体内的函数。

    嵌套函数可以捕获其外部函数所有的参数以及定义的常量和变量。

    看这个例子:

    import Cocoa
    
    func makeIncrementor(forIncrement amount: Int) -> () -> Int {
        var runningTotal = 0
        func incrementor() -> Int {
            runningTotal += amount
            return runningTotal
        }
        return incrementor
    }
    
    let incrementByTen = makeIncrementor(forIncrement: 10)
    
    // 返回的值为10
    incrementByTen()
    
    // 返回的值为20
    incrementByTen()
    
    // 返回的值为30
    incrementByTen()
    
    // 返回的值为40
    incrementByTen()
    
    let alsoIncrementByTen = incrementByTen
    
    // 返回的值也为50
    print(alsoIncrementByTen())

    一个函数makeIncrementor ,它有一个Int型的参数amout, 并且它有一个外部参数名字forIncremet,意味着你调用的时候,必须使用这个外部名字。返回值是一个()-> Int

    50

    위 프로그램 실행의 출력은 다음과 같습니다.

    rrreee

    Trailing closure

    후행 클로저는 함수 괄호 뒤에 작성된 클로저 표현식이며, 함수는 이를 마지막 매개변수로 호출하는 것을 지원합니다.

    rrreee

    Instance

    rrreee

    sort() { $0 > $1}은 후행 클로저입니다.

    위 프로그램 실행의 출력 결과는 다음과 같습니다.
    rrreee

    참고: 함수에 하나의 매개변수인 클로저 표현식만 필요한 경우 후행 클로저를 사용할 때 ()를 생략할 수도 있습니다.

    rrreee

    값 캡처

    클로저는 정의된 컨텍스트에서 상수나 변수를 캡처할 수 있습니다.

    이러한 상수와 변수가 정의된 원래 도메인이 더 이상 존재하지 않더라도 클로저는 여전히 클로저 함수 본문에서 이러한 값을 참조하고 수정할 수 있습니다.

    Swift에서 가장 간단한 클로저 형태는 다른 함수의 함수 본문 내에 정의된 함수인 중첩 함수입니다.

    중첩 함수는 정의된 상수 및 변수뿐만 아니라 외부 함수의 모든 매개변수를 캡처할 수 있습니다.
이 예를 보세요: 🎜rrreee🎜 함수 makeIncrementor에는 Int 유형 매개변수 amout이 있고 외부 매개변수 이름 forIncremet이 있습니다. 즉, 호출할 때 이 외부 이름을 사용해야 합니다. 반환 값은 ()-> Int 함수입니다. 🎜🎜함수 질문에는 runningTotal 변수와 함수 증분자가 선언되어 있습니다. 🎜🎜incrementor 함수는 매개변수를 얻지 못하지만 runningTotal 및 amount 변수는 함수 본문에서 액세스됩니다. 이는 이를 포함하는 함수 본문 내에 이미 존재하는 runningTotal 및 amount 변수를 캡처하여 그렇게 하기 때문입니다. 🎜🎜금액 변수는 수정되지 않기 때문에 증분기는 실제로 변수의 복사본을 캡쳐하여 저장하며, 그 복사본은 증분기와 함께 저장됩니다. 🎜🎜따라서 이 함수를 호출하면 다음이 누적됩니다. 🎜rrreee🎜위 프로그램의 실행 출력은 다음과 같습니다. 🎜rrreee🎜🎜클로저는 참조 유형입니다.🎜🎜위 예에서 incrementByTen은 상수이지만 클로저는 다음을 가리킵니다. 이러한 상수를 사용하면 캡처하는 변수의 값이 증가할 수 있습니다. 🎜🎜함수와 클로저 모두 참조 유형이기 때문입니다. 🎜🎜함수/클로저를 상수에 할당하든 변수에 할당하든 실제로는 상수/변수의 값을 해당 함수/클로저에 대한 참조로 설정하는 것입니다. 위의 예에서 incrementByTen이 가리키는 클로저에 대한 참조는 클로저 콘텐츠 자체가 아니라 상수입니다. 🎜🎜이는 또한 두 개의 서로 다른 상수/변수에 클로저를 할당하면 두 값이 모두 동일한 클로저를 가리킨다는 것을 의미합니다. 🎜rrreee🎜위 프로그램 실행의 출력은 다음과 같습니다: 🎜rrreee🎜🎜