7일차 - 21.06.14

수킴·2021년 6월 14일
0

100DaysOfSwift

목록 보기
8/37
post-thumbnail

학습키워드

  • closures

1. Using closures as parameters when they accept parameters

함수에 전달하는 클로저는 자체 매개변수를 받을 수도 있습니다.

클로저를 함수를 호출할 때 작성해줘서 함수에서 사용

func travel(action: (String) -> Void) {
    print("I'm getting ready to go.")
    action("London")
    print("I arrived!")
}

travel { (place: String) in
    print("I'm going to \(place) in my car")
}

// 실행결과
I'm getting ready to go.
I'm going to London in my car
I arrived!

2. Using closures as parameters when they return values

함수에 전달하는 클로저는 반환값을 지정할 수 있습니다.

반환하는 클로저를 함수를 호출할 때 작성해줘서 함수에서 사용

func travel(action: (String) -> String) {
    print("I'm getting ready to go.")
    action("London")
    print("I arrived!")
}

var result: String = ""

travel { (place: String) -> String in
    result = "\(place)도착"
    return result
}

print(result)

// 실행결과
I'm getting ready to go.
I arrived!
London도착

반환값이 있는 클로저를 사용하는 예제 - reduce()

3. Shorthand parameter names

함수에 선언한 클로저매개변수가 명확할 경우 후행클로저에서 매개변수를 생략할 수 있습니다.

func travel(action: (String) -> String) {
    print("I'm getting ready to go.")
    let description = action("London")
    print(description)
    print("I arrived!")
}

travel { (place: String) -> String in
    return "I'm going to \(place) in my car"
}

// MARK - 매개변수가 String인 것을 알기 때문에 생략 가능
travel { place -> String in
    return "I'm going to \(place) in my car"
}

// MARK - 반환값이 String인 것을 알기 때문에 생략 가능
travel { place in
    return "I'm going to \(place) in my car"
}

// MARK - 반환하는 코드가 한줄이므로 return 생략 가능
travel { place in
    "I'm going to \(place) in my car"
}

// MARK - 매개변수자체 생략 가능 
travel {
    "I'm going to \($0) in my car"
}

스위프트는 클로저를 작성할 때 매개변수를 단축인자이름을 제공합니다.

클로저구문은 자동으로 매개변수 이름에 $0, $1, $2 등등 단축인자이름을 제공합니다.

단축인자는 모든 타입을 제공합니다.

❗️ 매개변수명을 지정한 경우 단축인자와 같이 사용하면 에러가 발생합니다.

  • 주의할 경우
    1. 매개변수가 너무 많은 경우 단축인자를 사용하지 않는 편이 낫습니다.
    2. 기능이 일반적으로 사용되는 경우 $0 의 의미를 쉽게 이해할 수 있어서 편리합니다.
    3. $0 단축인자가 여러번 사용되는 경우 주의합니다.

4. Closures with multiple parameters

클로저에 여러매개변수를 추가할 수 있습니다.

클로저는 많은 매개변수를 사용할 수 있지만, 일반적으로 0 ~ 3개의 매개변수를 자주 사용합니다. 그 결과, $0, $1, $2 까지 이해하기 편립한다.

func travel(action: (String, Int) -> String) {
    print("I'm getting ready to go.")
    let description = action("London", 60)
    print(description)
    print("I arrived!")
}

travel {
    "I'm going to \($0) at \($1) miles per hour."
}

5. Returning closures from functions

함수에서 반환된 클로저를 가져올 수 있습니다.

-> 를 두번사용합니다. 한 번은 함수의 반환 값을 지정하고 두번 째는 클로저의 반환값을 지정합니다.

func travel() -> (String) -> Void {
    return {
        print("I'm going to \($0)")
    }
}

let result = travel() // (String) -> () 타입 클로저반환
result("London") // 클로저에 매개변수 선언

let result2 = travel()("London") // 한번에 사용

How Do I Declare a Closure - 클로저 구문

6. Capturing values

클로저 내부에서 외부 값을 사용하는 경우 스위프트는 이 값을 캡처합니다. 클로저와 함께 저장하므로 수정할 수 있습니다.

func travel() -> (String) -> Void {
    var counter = 1
    
    return {
        print("\(counter). I'm going to \($0)")
        counter += 1
    }
}

let result = travel()
result("London")
result("London")
result("London")
result("London")

// 실행 결과
1. I'm going to London
2. I'm going to London
3. I'm going to London
4. I'm going to London

캡처 기능이 있는 이유가 뭘까?

캡처기능이 있어서 클로저가 작동하는 데 필요한 데이터에 접근할 수 있습니다.

예를 들어 앞 뒤 번호가 같은 경우 겹치는 값이 안나오게 하려고 하는 경우

// MARK - 원하는 값이 나오지 않고 겹쳐서 난수 발생
func makeRandomNumberGenerator() -> () -> Int {
    return {
        var previousNumber = 0
        var newNumber: Int

        repeat {
            newNumber = Int.random(in: 1...3)
        } while newNumber == previousNumber

        previousNumber = newNumber
        return newNumber
    }
}

let generator = makeRandomNumberGenerator()

for _ in 1...10 {
    print(generator(), terminator: "")
}
// 실행결과
2312232333

var previousNumber = 0 을 클로저 외부에서 캡처해서 사용하도록 하면 반복해서 0이 저장되지 않기 때문에 겹치지 않는 결과가 나타납니다.

https://alisoftware.github.io/swift/closures/2016/07/25/closure-capture-1/

링크

100 Days of Swift - Day 7 - Hacking with Swift

profile
iOS 공부 중 🧑🏻‍💻

0개의 댓글