Swift

Swift | 클로저 closure

iOSDEv 2024. 2. 7. 11:14
클로저란?
(이름이 없는 함수)
함수의 기능가 완전히 동일하고 형태만 다르다

c#에서 사용했던 람다와 동일

내가 느낀바로는 함수와 클로저의 차이라고 생각한다면 함수는 이름이 있는 코드의 묶음으로 다른 코드가 함수이름으로 호출하여 사용할 수 있지만 클로저는 함수의 이름이 없어도 호출 할 수 있는 형태로 사용된다라고 느꼈다

 

함수는 타입이다
- 함수를 변수에 할당할 수 있음
- 함수를 호출할 때 함수를 파라미터로 전달할 수 있음
- 함수에서 함수를 반환할 수 있음

 

클로저의 기본형태

 

클로저는 변수에 담는 방법

 

함수에서 클로저 형태 변경 해보기

sum 함수를 클로저 형태로 변경하고 싶다면?

 

 

 

타입 추론에의해 타입이 생략이 가능하다 

 

 

클로저를 파라미터 안에 넣을 수 있다!
(콜백함수)
= 나중에 다시 호출하기 때문에 콜백함수라고 부름

 

  • 예시1

사후적 정의는 아주 많이 사용하는 경우이다 그래서 다른 언어에서 사용할 때도 람다(클로저)를 많이 사용했었다

 

 

  • 예시2

 

 

 

클로저를 간소화하기
 - 문맥상에서 파라미터와 리턴밸류 타입 추론(Type Inference)

 -  싱글 익스프레션인 경우(한줄), 리턴을 안 적어도 됨(Implicit Return)

 -  아규먼트 이름을 축약(Shorthand Argements) $0, $1

 -  트레일링 클로저 문법: 함수의 마지막 전달 인자(아규먼트)로 클로저 전달되는 경우, 소괄호를 생략 가능(후행클로저문법)

 

  • 후행 클로저 문법
    • 함수의 마지막 전달 인자를 클로저 전달되는 경우 소괄호 생략이 가능하다

 

 

 

  • 타입추론

 

  • 아규먼트 축약

$0 첫 번째 파라미터

$1 두 번째 파라미터

 

//예시
let closureType1 = { (param) in
    return param % 2 == 0
}

let closureType2 = { $0 % 2 == 0 }





let closureType3 = { (a: Int, b:Int) -> Int in
    return a * b
}

let closureType4: (Int, Int) -> Int = { (a, b) in
    return a * b
}

//타입을 반드시 명시해줘야한다
let closureType5: (Int, Int) -> Int = { $0 * $1 }

 

 

//예시2

//Timer.scheduledTimer(withTimeInterval: 0.2, repeats: false, block: <#T##(Timer) -> Void#>)
//false 반복하지 않는거
//형태가 함수며 미리 구현해둔 클로저
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { (timer) in
    print("0.5초뒤에 출력하기")
}



//vc.dismiss(animated: true, completion: <#T##(() -> Void)?##(() -> Void)?##() -> Void#>)
//화면을 닫는 메서드
vc.dismiss(animated: true) {
    print("화면을 닫는 것을 완료했습니다.")
}


//UIView.animate(withDuration: <#T##TimeInterval#>, animations: <#T##() -> Void#>, completion: <#T##((Bool) -> Void)?##((Bool) -> Void)?##(Bool) -> Void#>)
UIView.animate(withDuration: <#T##TimeInterval#>) {
    <#code#>
} completion: { (<#Bool#>) in
    <#code#>
}

 

completion / completionHandler 
: 보통 콜백함수라고 생각하면 됨

 

 

// 아규먼트 레이블을 생략하는 경우
// 와일드 카드 패턴 사용시
func multipleClosure2(first: () -> (), _ second: () -> (), third: () -> ()) {
    first()
    second()
    third()
}

//매개변수위 클릭 후 엔터만 치면 알아서 변경됨
/*
multipleClosure2 {
    <#code#>
} _: {
    <#code#>
} third: {
    <#code#>
}
*/

// 아큐먼트 레이블을 생략하지 못함
//레이블 따위를 생략하지 못해서 그냥 사용해야함
multipleClosure2 {
    print("1")
} _: {
    print("2")
} third: {
    print("3")
}

 

예전에는 마지막만 후행클로저가 가능했지만 현재는 여러개 함수를 파라미터로 넣어도 편하게 사용할 수 있다

 

클로저 타입은?

참조 타입

값의 저장은 heap (주소는 stack에 저장)

RC를 통해 메모리 관리

클래스와 동일한 참조타입이기 때문에 이러한 현상이 발생함

 

escaping
  • 함수의 실행이 종료되면 파라미터로 쓰이는 클로저도 제거됨
  • @escaping 키워드는 클로저를 제거하지 않고 함수에서 탈출시킴
    • 함수 내부에서 사용한 클로저를 외부 변수에 저장
    • GCD(비동기 코드 사용)

 

autoclosure : 자동으로 클로저를 만들어주는 경우
기본적으로 non-escaping 특성을 가지고 있음

 

  • 파라미터가 없는 경우에만 사용

  • 사용을 지양해라고함
    • 번거로움을 해결해주긴함
  • 잘사용하진 않음
  • 일반적으로 클로저를 써도 되지만 너무 번거로울 때 사용

 

인프런 앨런 Swift문법 마스터 스쿨을 듣고 정리하였습니다