본문 바로가기

스위프트

스위프트 클로저(feat. 함수)

스위프트 클로저(feat.  함수)

스위프트를 배우면서 클로저라는 낯선 문법을 발견해서 정리해 두기 위한 포스팅이다. 함수에 대해서 잘 모른다면 함수를 먼저 알고 오도록 하자. 클로저는 함수와 유사하게 쓰인다. 

 

다음 예시 코드를 보도록 하자.

func sayHello () {
  print("Hello!")
}

 

Hello라는 텍스트를 출력하는 sayHello라는 이름의 함수이다. 클로저를 이용해 표현해보도록 하겠다.

 

 

let sayHello = { print("Hello!") }

함수에서 작동하던 것을 그대로 표현하고 sayHello라는 상수에 할당하고 있다.  위 두 코드는 똑같은 기능을 한다고 봐도 무방하다.

 

함수와 마찬가지로 argument를 받고 결과 값을 return하도록 할 수 있다. 일단 함수로 먼저 표현해보겠다.

func multiply (_ input1: Int, _ input2 : Int) -> Int {
	return input1 * input2
}

두 개의 Int값을 받아 두 값을 곱한 값을 return하는 함수이다. 다음은 클로저이다.

 

let multiply = {(_ input1: Int, _ input2: Int) -> Int in
	return input1 * input2
}

두 개의 Int값을 받아 두 값을 곱한 값을 return하는 클로저이다. multiply이라는 상수에 할당하고 있다.

중괄호로 묶고 그안에 함수의 argument의 타입을 명시하는 것과 같이 표현하고 있다. 결과 값의 타입을 명시하는 부분도 함수와 마찬가지로 -> Int라고 적은 부분을 볼 수 있을 것이다. 그 다음이 함수랑 다른 부분인데 In이라는 키워드 뒤에 실행하는 코드를 적고 있다.

 

이렇듯 약간의 표기 방법만 다를 뿐 큰 차이는 없다. 함수는 선언할 때 이름이 있다는 점? 그 정도가 다르다고 하겠다.

 

 

클로저에 좀 더 자세히 알아보자.

 

클로저는 타입에 대해서 자유로운 편이다.

타입을 지정하지 않고 클로저를 사용해보자.

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
var reversedNames = names.sorted(by: { (s1, s2) in
    return s1 > s2
})
// ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

s1, s2에 타입을 명시하지 않은 것을 볼 수 있다. 컴파일러가 알아서 추론해준다. 여기서는 String이라고 컴파일러가 추론했을 것이다.

 

한줄짜리 표현에서 return 생략 가능

이건 함수와 같은 특징이다.

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
var reversedNames = names.sorted(by: { (s1, s2) in
   s1 > s2 // return 생략
})
// ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

 

argument 이름의 축약어 사용 가능

축약어는 첫 번째 인자가 $0, 두 번째가 $1, 세 번째가 $2 .. 이런 식이다. 

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
var reversedNames = names.sorted(by: { $0 > $1 } )

가독성은 .. 잘 모르겠다

 

Trailing Closures 함수의 마지막 인자가 클로저 표현식인 경우, 소괄호() 뒤에 중괄호 {}로 빼내어 쓸 수 있다.

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
var reversedNames = names.sorted() { $0 > $1 } // 괄호 뒤에 클로저 입력

함수의 마지막 argument로 클로저가 들어갈 경우 소괄호도 생략이 가능하다.

 

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
var reversedNames = names.sorted { $0 > $1 } // 소괄호까지 생략

 

SwiftUI에 사용되는 HStack, VStack 등이 Trailing Closure 방식으로 쓰인다.

HStack {
  Text("Hello,")
  Text("World!")
}