함수
함수는 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 |