본문 바로가기
모바일앱/Swift

Collection - Closure, Capturing Values

by GeekCode 2021. 10. 10.
반응형

 

Collection - Closure

 

{ (  parameters  ) -> returntype in

    statements

}

 

클로저 란? 이름이 없는 Method 혹은 함수 이다

공식 문서링크

https://docs.swift.org/swift-book/LanguageGuide/Closures.html

 

Global and nested functions, as introduced in Functions, are actually special cases of closures. Closures take one of three forms:

  • Global functions are closures that have a name and don’t capture any values.
  • Nested functions are closures that have a name and can capture values from their enclosing function.
  • Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.

// Closure는 3가지가 있다.

// Global 함수

// Nested 함수

// Closure Expressions -> 우리가 배우고 있는 것

 

함수와 클로저의 비교

Function(Global) Closure
이름이 있다 이름이 없다
func 키워드 필요 func 키워드 필요 없음
인자를 받을 수 있다.
값을 리턴할 수 있다.
변수로 할당 할 수 있다.
First Class Type이다.

 

First Class Type?

어떤 언어든지 새로 공부하다보면 언어에서 제공하는 타입에 대해 이야기 할때 이런말을 사용한다.

대표적으로 Int를

  • 변수에 할당할 수 있다.
  • 인자로 받을 수 있다.
  • 리턴할 수 있다.

함수와 클로저 또한 위 내용과 같다.

 

실무에서의 사용

  • Completion Block
  • Higher Order Functions

Completion Block 

어떤 task가 완료가 되었을때, 클로저가 수행되면서 자주쓰임 

예1) 앱에서 네트워크를 통해서 데이터를 받아올때, 네트워크 상황에 따라 데이터 전송이 빠를 수도 느릴 수도 있다. 이렇게 비동기적으로 언제 끝날지 모르는 경우에는 해당 일이 끝나고 뭔가를 수행해야할 때 클로저를 수행한다.

 

네트워크 받아지면, 화면에 그려줘야함 > 데이터를 화면에 그려주는 코드 블록

Completion Block  -> 뭔가가 완료되면 돌아가야하는 코드 블록

 

Higher Order Functions (고계함수, 고차함수)

input으로 함수를 받을 수 있는 유형의 함수  (인자를 함수로 받을 수 있는 함수)

 

input으로 함수를 넘겨줄때, 함수를 만들어서 줘도 되지만 

즉시 고계함수를 사용하는 자리에서 클로저를 만들어서 넘겨줄 수도 있다.

 

대표적인 고계함수는 Collection에서 확인하게 되는사용하는 map, filter, reduce 로 빈번한 for 과 while의 사용을 줄 일 수 있다.

 

 

클로저의 이용

{ (  parameters  ) -> returntype in

    statements

}

 

 

 

 

// 두개의 수를 곱하는 클로저
//이부분이 함수와 매우 비슷한 모양이다. 하지만 파라미터 이름이 따로 없음

var multiplyClosure:(Int,Int) -> Int = { (a: Int, b: Int) -> Int in
    return a * b
}
// 짧게
//var multiplyClosure:(Int,Int) -> Int = { return $0 * $1 }
//var multiplyClosure:(Int,Int) -> Int = { $0 * $1 }

//줄이는 것이 강점이지만 너무 줄이면 의미를 알아보기 힘들 수 있다.
//
//var multiplyClosure:(Int,Int) -> Int = { a, b in
//    return a * b
//}
//multiplyClosure(4,2) //8

// 여기까진 아직 클로저의 장점이 느껴지지 않음

// 실무에서는 메소드 혹은 함수가 클로저를 파라미터로 받는 경우가 많다.

func operateTwoNum(a:Int, b:Int, operation: (Int,Int)-> Int) -> Int {
    let result = operation(a,b) // 세번째 파라미터가 클로저
    return result
}

operateTwoNum(a: 4, b: 2, operation: multiplyClosure) //8

var addClosure : (Int, Int) -> Int = { a, b in
    return a + b
}

operateTwoNum(a: 4, b: 2, operation: addClosure) //6

//즉석에서 함수안에 클로저를 만들 수도 있다.
operateTwoNum(a: 4, b: 2) {a,b in
    return a / b
}

 

Capturing Values

scope는 크게 두가지가 있다. 바깥쪽 scope, 안쪽 scope

보통 안쪽에 있는 변수는 바깥족에서 사용할 수 없다.

하지만 클로저에 잡히면 변수를 바깥에서도 사용할 수 있다.   captured 되었다고한다.

//Capturing Values

// scope는 크게 두가지가 있다. 바깥쪽 scope, 안쪽 scope
// 보통 안쪽에 있는 변수는 바깥족에서 사용할 수 없다.
//하지만 클로저에 잡혀서 바깥에서도 사용할 수 있다.   captured 되었다고한다.


//if true {
//    let name = "Jason"
//    printClosure = {
//        print(name)
//    }
//}
// ->

// input만 있고 output이 없는 클로저
let voidClosure: () -> Void = {
    print("iOS 개발자 짱")
}

voidClosure() // iOS 개발자 짱

// Capturing Values

var count = 0

let incrementer = {
    count += 1
}
incrementer()
incrementer()
incrementer()
incrementer()
count
//count는 범위를 벗어났지만 클로저에 잡혀있기 때문에 변화한다.
//이것때문에 문제가 생길수도, 편리할 수도 있다.

 

 

 

클로저 실습

// Closure 실습
/*
{ (<#parameters#>) -> <#return type#> in
    <#statements#>
}
 */
// ex1. 초 심플 클로저  -> statement에 아무것도 안씀
//let choSimpleClosure = {
//
//}//파라미터도 없고, 스테이트먼트도, 리턴도 없고
////수행방법
//choSimpleClosure()


// ex2. 코드블록을 구현한 클로저 -> statement에 씀
//let choSimpleClosure = {
//    print("Hello, 클로저, 코로나 하이")
//}
//choSimpleClosure()

// ex3. 인풋 파라미터를 받는 클로저
//let choSimpleClosure:(String) -> () = { name in

//let choSimpleClosure:(String) -> Void = { name in
//    print("Hello, 코로나 하이! 나의이름은 \(name)입니다")
//}
//choSimpleClosure("코로나가 제일싫어") //Hello, 코로나 하이! 나의이름은 코로나가 제일싫어입니다
//

// ex4. 값을 리턴하는 클로저

//let choSimpleClosure:(String) -> String = { name in
//    print("Hello, 코로나 하이! 나의이름은 \(name)입니다")
//} //Cannot convert value of type '()' to closure result type 'String' -> 리턴이 없음

//let choSimpleClosure:(String) -> String = { name in
//    let message = "iOS 개발 만만세 \(name)님 경제적자유를 얻으실 거에요"
//    return message
//}
//let result = choSimpleClosure("코로나가 제일싫어")
//print(result) //iOS 개발 만만세 코로나가 제일싫어님 경제적자유를 얻으실 거에요


// ex5. Closure를 파라미터로 받는 함수 구현

//func sameSimpleFunction(choSimpleClosure: () -> Void) {
//    print("함수에서 호출이 되었어요")
//}
//sameSimpleFunction(choSimpleClosure: {
//    print("헬로 코로나 from Closure")
//}) // 위 함수에서 사용을 안함

//func sameSimpleFunction(choSimpleClosure: () -> Void) {
//    print("함수에서 호출이 되었어요")
//    choSimpleClosure()
//}
//sameSimpleFunction(choSimpleClosure: {
//    print("헬로 코로나 from Closure")
//})
//함수에서 호출이 되었어요
//헬로 코로나 from Closure



// ex6. Trailing Closure

//다른 파라미터도 받음
func sameSimpleFunction(message: String, choSimpleClosure: () -> Void) {
    print("함수에서 호출이 되었어요, 메세지는 \(message)")
    choSimpleClosure()
}

//sameSimpleFunction(message: "로나로나메로나, 코로나는 극혐", choSimpleClosure: {
//    print("헬로 코로나 from Closure")
//})
//함수에서 호출이 되었어요, 메세지는 로나로나메로나, 코로나는 극혐
//헬로 코로나 from Closure

//인자가 점점 많아지면 코드가 지저분해진다. message: value:3, object: Struct,choSimpleClosure: {
//print("헬로 코로나 from Closure")
//})

//-> 인자가 여러개 있고 클로저도 인자로 받을때, 마지막 인자가 클로저라면, 코드적으로 생략가능
//sameSimpleFunction(message: "로나로나메로나, 코로나는 극혐", choSimpleClosure: {
//    print("헬로 코로나 from Closure")
//})
sameSimpleFunction(message: "로나로나메로나, 코로나는 극혐") {
    print("헬로 코로나 from Closure")
}
// 둘다 같은 내용을 수행한다.


//한개만 있는 경우

//함수에서 호출이 되었어요, 메세지는 로나로나메로나, 코로나는 극혐
//헬로 코로나 from Closure

//둘다해서 축약까지
//
//함수에서 호출이 되었어요, 메세지는 로나로나메로나, 코로나는 극혐
//헬로 코로나 from Closure
//함수에서 호출이 되었어요, 메세지는 로나로나메로나, 코로나는 극혐
//헬로 코로나 from Closure


//아래 축약만 있는 경우
//함수에서 호출이 되었어요, 메세지는 로나로나메로나, 코로나는 극혐
//헬로 코로나 from Closure
반응형

'모바일앱 > Swift' 카테고리의 다른 글

프로퍼티 개념  (0) 2021.10.13
프로토콜  (0) 2021.10.13
Struct만들기 도전과제  (0) 2021.10.12
구조체와 클래스의 차이점  (0) 2021.10.11
Collection - Set  (0) 2021.10.10
Collection - Dictionary  (0) 2021.10.10
Collection - Array  (0) 2021.10.09
옵셔널 도전과제  (0) 2021.10.08