ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Swift 5.6 Closures
    기술/iOS 2022. 3. 20. 17:43

    Closures

    클로저는 정의된 컨텍스트에서 모든 상수와 변수에 대한 참조를 캡처하고 저장할 수 있습니다. 이러한 상수와 변수를 폐쇠라고 합니다.

    함수에서 소개한 전역과 중첩함수는 클로저의 특별한 케이스입니다. 클로저는 3가지 형태 중 하나를 취합니다.

    • 전역함수는 이름을 가지고 어떠한 값도 캡처하지 않는 클로저입니다.
    • 중첩함수는 이름을 가지고 둘러싼 함수로부터 값을 캡처할 수 있는 클로저입니다.
    • 클로저 표현식은 주변 컨텍스트에서 값을 캡처할 수 있는 경량 구문으로 작성된 이름 없는 클로저입니다.

    Swift 에서 클로저 표현식은 일반 시나리오에서 간단하고 깔끔한 구문을 장려하는 최적화를 통해 깔끔하고 명료한 스타일을 가지고 있습니다.

    • 컨텍스트에서 파라미터와 반환값 유추
    • 단일 표현식 클로저 암시적 반환
    • 약식 인자 이름
    • 후행 클로저 구문

    Closure Expressions

    클로저 표현식은 간단하고 집중적인 구문으로 인라인 클로저로 작성하는 방법입니다. 클로저 표현식은 명확성이나 의도를 잃지 않고 짧은 형태로 클로저를 작성하기 위한 몇가지 구문 최적화를 가지고 있습니다. 각 예제는 동일한 기능을 보다 간결한 방식으로 표현합니다.

    The Sorted Method

    Swift 의 표준 라이브러리를 사용자가 제공하는 정렬 클로저의 출력을 기반으로 알려진 타입의 값을 정렬하는 sorted(by:) 라는 메서드를 제공합니다.

    이 예제는 String 값의 배열을 정렬하고 정렬 클로저는 (String, String) -> Bool 타입의 함수를 필요로 합니다.

    정렬 클로저를 제공하는 한 가지 방법은 올바른 타입의 일반 함수를 작성하고 메서드에 인자로 전달하는 것입니다.

    func backward(_ s1: String, _ s2: String) -> Bool {
        return s1 > s2
    }
    var reversedNames = names.sorted(by: backward)
    // reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]
    

    Closure Expression Syntax

    클로저 표현구는 아래와 같은 일반적인 형태를 가지고 있습니다

    클로저 표현구 파라미터는 in-out 파라미터일 수 있지만 기본 값을 가질 수 없습니다. 가변 파라미터를 사용할 수 있습니다. 튜플은 파라미터 타입과 반환 타입으로 사용할 수 있습니다.

    reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
        return s1 > s2
    })
    

    클로저의 바디의 시작은 in 키워드로 시작합니다. 이 키워드는 클로저의 파라미터와 리턴 타입 정의가 끝남을 나타내며 클로저의 바디가 시작함을 나타냅니다.

    바디가 너무 짧기 때문에 한 줄로 작성할 수 있습니다.

    reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )
    

    Inferring Type From Context

    정렬 클로저는 메서드에 인자로 전달되기 때문에 Swift 파라미터 타입과 반환되는 값의 타입을 유추할 수 있습니다. 즉, 클로저 표현식 정의에 일부러 작성할 필요가 없음을 의미합니다.

    reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
    

    함수나 메서드에 클로저를 인라인 클로저 표현식으로 전달할 때 항상 파라미터 타입과 반환 타입을 유추할 수 있습니다. 결과적으로 클로저가 함수 또는 메서드 인자로 사용될 때 완전한 형태로 인라인 클로저를 작성할 필요가 없습니다.

    Implict Returns from Single-Expression Closures

    단일 표현 클로저는 이전 예제에서 return 키워드를 생략하여 단일 표현식을 암시적으로 반환할 수 있습니다.

    reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
    

    Shorthand Argument Names

    Swift 는 인라인 클로저에 $0 , $1 등 클로저의 인자값으로 참조하는데 사용할 수 있는 자동적으로 생성된 짧은 인자 이름을 제공합니다.

    클로저 표현식에 이런 짧은 인자 이름을 사용한다면 선언에 클로저의 인자 목록을 생략할 수 있고 인자의 이름의 수와 타입은 함수 타입에서 유추됩니다. 클로저 표현식이 전체 바디로 구성되기 때문에 in 키워드를 생략할 수도 있습니다.

    reversedNames = names.sorted(by: { $0 > $1 } )
    

    Operator Methods

    여기서 더 짧게 작성하는 방법이 있습니다. Swift 의 String 타입은 보다 큰 연산자의 문자열 별 구현을 String 타입의 파라미터 2개가 있는 메서드로 정의하고 Bool 타입을 반환합니다. 이것은 sorted(by:) 메서드에 필요한 메서드 타입과 정확히 일치합니다. 따라서 간단하게 보다 큰 연산자를 전달할 수 있고 Swift 는 문자열 특정 구현을 사용하기 원한다고 유추합니다.

    reversedNames = names.sorted(by: >)
    

    Trailing Closures

    함수 마지막 인자로 함수에 클로저 표현식을 전달해야하고 클로저 표현식이 긴 경우 후행 클로저로 작성하는 것이 유용할 수 있습니다. 후행 클로저는 함수의 인자이지만 함수 호출의 소괄호 다음 작성합니다. 후행 클로저 구문을 사용할 때 함수 호출의 일부로 첫번째 클로저 인자 라벨을 작성하지 않아도 됩니다. 함수 호출은 여러개의 후행 클로저를 포함할 수 있지만 아래 몇가지 예제에서는 단일 후행 클로저를 사용합니다.

    reversedNames = names.sorted() { $0 > $1 }
    

    유일한 인자인 경우 소괄호를 작성하지 않아도 됩니다.

    reversedNames = names.sorted { $0 > $1 }
    

    후행 클로저는 길어서 한줄로 인라인 작성이 불가능할 때 유용합니다.

    let strings = numbers.map { (number) -> String in
        var number = number
        var output = ""
        repeat {
            output = digitNames[number % 10]! + output
            number /= 10
        } while number > 0
        return output
    }
    // strings is inferred to be of type [String]
    // its value is ["OneSix", "FiveEight", "FiveOneZero"]
    

    함수가 여러개의 클로저를 가지고 있다면 첫번째 후행 클로저의 인자 라벨은 생략하고 남은 후행 클로저 라벨은 표기합니다.

    func loadPicture(from server: Server, completion: (Picture) -> Void, onFailure: () -> Void) {
        if let picture = download("photo.jpg", from: server) {
            completion(picture)
        } else {
            onFailure()
        }
    }
    
    loadPicture(from: someServer) { picture in
        someView.currentPicture = picture
    } onFailure: {
        print("Couldn't download the next picture.")
    }
    

    Capturing Values

    클로저는 정의된 둘러싸인 컨텍스트에서 상수와 변수를 캡처할 수 있습니다. 그러면 클로저는 상수와 변수를 정의한 원래 범위가 더 이상 존재하지 않더라도 바디 내에서 해당 상수와 변수를 참조하고 수정할 수 있습니다.

    ? Closures are Reference Types

    뭘 이야기하고 싶었던 걸까?

    ? Escaping Closures

    어떻게 정의하고 설명해야할지 모르겠다

    내가 아는건 함수 반환 후 실행된다는 것 까지

    ? Auto Closures

    자동 클로저는 함수에 인자로 전달되는 표현식을 래핑하기 위해 자동으로 생성되는 클로저 입니다. 인자를 가지지 않으며 호출될 때 내부에 래핑된 표현식의 값을 반환합니다. 이러한 구문상의 편의를 통해 명시적 클로저 대신 일반 표현식을 작성하여 함수의 파라미터 주위의 중괄호를 없앨 수 있습니다.

    자동 클로저를 가지는 함수를 호출하는 것은 일반적이지만 이러한 함수를 구현하는 것은 일반적이지 않습니다.

    클로저가 호출될 때까지 코드 내부 실행이 되지 않기 때문에 자동 클로저는 판단을 지연시킬 수 있습니다. 판단 지연은 코드 판단 시기를 제어할 수 있기 때문에 사이드 이펙트가 있거나 계산이 오래 걸리는 코드에 유용합니다.

    어떻게 쓰라는 걸까?

    '기술 > iOS' 카테고리의 다른 글

    Swift 5.6 Structures and Classes  (0) 2022.03.20
    Swift 5.6 Enumerations  (0) 2022.03.20
    Swift 5.6 Functions  (0) 2022.03.20
    Swift 5.6 Control Flow  (0) 2022.02.26
    Swift 5.6 Arrays  (0) 2022.02.26

    댓글 0

Designed by Tistory.