본문 바로가기

모바일/스위프트

[Swift] 함수와 클로저

함수

함수는 func 키워드를 사용하여 정의, -> 를 사용해서 함수의 반환 타입을 지정

func hello(name: String, time:Int) -> String {
  var string = ""
  for _ in 0..<time {
    string += "\(name)님 안녕하세요! \n"
  }
  return string
}

 

Swift에서는 독특하게 함수 호출 시 파라미터 이름을 함께 작성

hello(name: "hoyhi", time: 3)

 

함수 호출 시 사용하는 파라미터 이름과 함수 내부에서 사용하는 파라미터 이름을 다르게 사용하고 싶은 경우

func hello(to name: String, numberOfTimes time: Int) {
  // 함수 내부에서는 `name` 과 `time` 을 사용
  for _ in 0..< time {
    print(name)
  }
}

hello(to: "전수열", numberOfTimes: 3) // 이곳에서는 `to`와 `numberOfTimes` 사용

 

파리미터 이름을 _로 정의하면 함수 호출 시 파라미터 이름 생략

func hello(_ name: String, time: Int) {
  // ...
}

hello("hoyhi", time: 3) // `name:` 이 생략

 

파라미터에 기본 값 지정

기본 값이 지정된 파라미터는 함수 호출시 생략 가능

func hello(name: String, time: Int = 1) {
  // ...
}

hello("hoyhi")

 

... 을 사용하면 개수가 정해지지 않은 파라미터를 받을 수 있음

func sum(_ numbers: Int...) -> Int {
  var sum = 0
  for number int numbers {
    sum += number
  }
  return sum
}

sum(1,2)
sum(3,4,5)

 

함수 안에 함수를 또 작성 가능

func hello(name: String, time: Int) {
  func message(name: sTring) -> String {
    return "\(name)님 안녕하세요!"
  }
  
  for _ in 0..<time {
    print(message(name: name))
  }
}

 

함수 안에 정의한 함수 반환

func helloGenerator(message: String) -> (String) -> String {
  func hello(name: String) -> String {
    return name + message
  }
  return hello
}

let hello = helloGenerator(message: "님 안녕하세요!")
hello("hoyhi")

여기서 핵심은 helloGenerator() 함수의 반환 타입이 (String) -> String 라는 것

즉, '문자열을 받아서 문자열을 반환하는 함수' 를 반환하는 함수

 

만약 helloGenerator() 안에 정의한 hello() 함수가 여러개의 파라미터를 받는다면

func helloGenerator(message: String) -> (String, String) -> String {
  func hello(firstName: String, lastName: String) -> String {
  	return lastName + firstName + message
  }
  return hello
}

let hello = helloGenerator(message: "님 안녕하세요!")
hello("hoy", "hi")

(String) -> String 이 (String, String) -> String으로 변경

 

클로저(Closure)

클로저는 중괄호 ( {} )로 감싸진 '실행 가능한 코드 블럭'

func helloGenerator(message: String) -> (String, String) -> String {
  return { (firstName: String, lastName: String) -> String in
    return lsatName + firstName + message
  }
}

 

함수는 이름이 있는 클로저

{ (firstName: String, lastName: String) -> String in
  return lastName + firstName + message
}

클로저는 중괄호로 감싸져 있는데 파라미터를 괄호로 감싸서 정의

함수와 마찬가지로 -> 를 사용하여 반환 타입 명시

차이점은 in 키워드를 사용해서 파라미터, 반환 타입 영역과 실제 클로저의 코드를 분리

 

첫번째 파라미터가 문자열, 두번째 파라미터도 문자열 이므로

func helloGenerator(message: String) -> (String,String) -> String {
  return {
    return $1 + $0 + message
  }
}

로 바꿔 쓸수 있고 클로저 내부의 코드가 한 줄이라면 아래 코드처럼 return도 생략가능

func helloGenerator(message: String) -> (String, String) -> String {
  return { $1 + $0 + message }
}

 

클로저는 변수처럼 정의 가능

let hello: (String, String) -> String = { $1 + $0 + "님 안녕하세요." }
hello("hi","hoy")

 

옵셔널 정의 가능, 옵셔널 체이닝도 가능

let hello: ((String, String) -> String)?
hello?("hi","hoy")

 

클로저를 변수로 정의하고 함수에서 반환하는 것 처럼 파라미터로 받기 가능

func manipulate(number: Int, using block: Int -> Int) -> Int {
  return block(number)
}

manipulate(number: 10, using: { (number: Int) -> Int in
  return number * 2
})

 

생략 가능

manipulate(number: 10, using: {
  $0 * 2
})

 

함수의 마지막 파라미터가 클로저라면, 괄호와 파라미터 이름까지 생략 가능

manipulate(number: 10) {
  $0 * 2
}

 

이런 구조로 만들어진 예시가 sort(), filter()

함수가 클로저 하나만을 파라미터로 받는다면 괄호를 아예 쓰지 않아도됨

let numbers = [1, 3, 2, 6, 7, 5, 8, 4]

let sortedNumbers = numbers.sort { $0 < $1 }
print(sortedNumbers) // [1, 2, 3, 4, 5, 6, 7, 8]

let evens = numbers.filter { $0 % 2 == 0 }
print(evens) // [2, 6, 8, 4]

 

클로저 활용

클로저는 sort(), filter() 와 같은 배열에 자주 쓰이고 이외에도 map(), reduce() 존재

 

map() 은 파라미터로 받은 클로저를 모든 요소에 실행하고 그 결과를 반환

예를 들어, 정수 배열의 모든 요소들에 2를 곱한 값으로 이루어진 배열을 만들고 싶다면 이렇게 작성

let arr1 = [1, 3, 6, 2, 7, 9]
let arr2 = arr1.map { $0 * 2 } // [2, 6, 12, 4, 14, 18]

 

reduce() 는 초깃값이 주어지고, 초깃값과 첫 번째 요소의 클로저 실행 결과, 그리고 그 결과와 두 번째 요소의 클로저 실행 결과, 그리고 그 결과와 세 번째 요소의 클로저 실행 결과, ... 끝까지 실행한 후의 값을 반환

 

바로 위에 정의한 arr1의 모든 요소의 합을 구하고 싶다면 이렇게 작성

arr1.reduce(0) { $0 + $1 } // 28

또는

arr1.reduce(0, +) // 28

'모바일 > 스위프트' 카테고리의 다른 글

[Swift] 아웃렛 변수와 액션 함수 문법  (0) 2021.07.08
[Swift] Xcode 프로젝트 생성  (2) 2021.07.07
[Swift] 옵셔널(Optional)  (0) 2021.07.05
[Swift] 조건문과 반복문  (0) 2021.07.05
[Swift] Swift란?  (0) 2021.07.05