Swift

Swift - 4. 함수, 메서드, 클로저 개요

iosos 2023. 12. 26. 16:40

함수

  • 특정 작업을 수행하기 위해 호출할 수 있게 이름 붙여진 코드 블록

 

매개 변수(parameter) vs 인자(argument)

  • 매개변수 : 함수가 호출될 때 받게 되는 값
  • 인자 : 실제로 함수가 호출되고 값이 전달되는 시점에서 인자로 부름

 

메서드

  • 특정 클래스나 구조체 또는 열거형과 연관된 함수
  • 클래스 내 함수 선언 → 메서드
  • 특별한 언급 없으면 함수 설명과 규칙, 동작이 모두 메서드에도 동일하게 적용됨

 

 

함수 선언 방법

  • 함수명, 매개변수, 반환 결과 타입의 조합 → 함수 시그니처
func 함수명 (매개변수 이름 : 매개변수 타입, ... ) -> 반환 결과 타입 {

	// 함수 코드
} 
// 매개변수로 문자열 하나와 정수 하나를 받으며 문자열 결과를 반환하는 함수
func buildMessageFor(name : String, count : Int) -> String {
	// "\(name), you are customer number \(count)"
    return "\(name), you are customer number \(count)"
	
}

print(buildMessageFor(name: "lee", count: 2))   // lee, you are customer number 2

→ 문자열 값을 반환하기 위해 return을 사용하지만, 함수가 단일 표현식을 가지고 있으면 생략 가능

 

 

지역 매개변수명과 외부 매개변수명

  • 지역 매개변수명 : 함수를 선언할 때 함수 코드 내에서 참조할 수 있는 이름을 할당한 매개 변수
  • 외부 매개변수명 : 함수가 호출될 때, 참조되는 매개변수의 이름
let message = buildMessageFor(name : "lee", count : 2)

→ name, count는 지역 매개변수명이자, 외부 매개변수명

 

 

  • 매개변수에 할당된 디폴트 외부 매개변수명은 지역 매개변수명 앞에 밑줄(_) 문자를 써서 없앨 수 있음
// 외부 매개변수명, 지역 매개변수명
func buildMessageFor(_ name : String, _ count : Int) -> String {
         "\(name), you are customer number \(count)"
}

let message = buildMessageFor("lee", 2) // "lee, you are customer number 2"

 

 

  • 지역 매개변수명, 외부 매개변수명 다르게 지정
// 외부 매개변수명, 지역 매개변수명
func buildMessageFor(userName name : String, userCount count : Int) -> String {
         "\(name), you are customer number \(count)"
}

let message = buildMessageFor(userName : "lee", userCount:  2) // "lee, you are customer number 2"

 

 

함수에 디폴트 매개변수 선언

  • 함수가 호출될 때 인자로 쓸 값이 들어오지 않은 경우에 사용할 디폴트 매개변수 값 지정
  • 디폴트 값을 매개변수의 끝에 둠
// 디폴트 매개변수
func buildMessageFor(_ name : String = "Customer", count : Int) -> String {
         "\(name), you are customer number \(count)"
}

let message = buildMessageFor(count : 2)
print(message)  // Customer, you are customer number 2

 

 

여러 결괏값 반환

  • 결괏값들을 튜플로 래핑하면 여러 개의 결과값을 함수로 반환 가능
  • 길이에 대하여 인치 단위의 측정값을 매개변수로 받음 → 이 값을 야드, 센치미터, 미터로 변환 후 하나의 튜플 인스턴스에 넣어 반환하는 함수
// 길이에 대하여 인치 단위의 측정값을 매개변수로 받음 → 이 값을 야드, 센치미터, 미터로 변환 후 하나의 튜플 인스턴스에 넣어 반환하는 함수
func sizeConverter(_ length: Float) -> (yards : Float, centimeters : Float, meters: Float){
    let yards = length * 0.0277778
    let centimeters = length * 2.54
    let meters = length * 0.0254
    return (yards, centimeters, meters)
}

let lengthTuple = sizeConverter(20)

print(lengthTuple.yards)        // 0.555556
print(lengthTuple.centimeters)  // 50.8
print(lengthTuple.meters)       // 0.508

 

 

가변 개수 매개변수 (variadic parameter)

  • 함수가 호출될 때 함수가 받게 될 매개변수가 몇 개인지 알 수 없는 경우 사용
  • 함수가 지정된 데이터 타입의 매개변수를 0개 또는 그 이상을 받는다는 의미 (… 점 3개 사용)
  • 함수 내에서 매개변수는 배열 객체의 형태로 사용
  • 문자열 값들을 매개변수로 받아 콘솔 패널에 출력하는 함수
//문자열 값들을 매개변수로 받아 콘솔 패널에 출력하는 함수
func displayStrings(_ strings: String...){
    for string in strings {
        print(string)
    }
}

displayStrings("one","two","three","four")

 

 

 

변수인 매개변수

  • 함수가 받는 모든 매개변수는 상수 취급 → 변경되는 것을 막음
  • 함수 내에서 매개변수의 값을 변경하고 싶으면 섀도 복사본(shadow copy)을 반드시 생성해야 함
  • 인치 단위의 길이와 너비를 매개변수로 전달받아 각각의 값을 센티미터로 변환 후 면적 계산 반환 함수
// 인치 단위의 길이와 너비를 매개변수로 전달받아 각각의 값을 센티미터로 변환 후 면적 계산 반환 함수
func calcuateArea(length : Float, width: Float) ->  Float{
    var length = length
    var width = width
    
    length = length * 2.54
    width = width * 2.54
    return length * width
}

print(calcuateArea(length: 10, width: 20))  // 1290.32

 

 

입출력 매개변수로 작업하기

  • 함수가 값을 반한환 뒤에도 매개변수에 대한 변경을 유지하려면, 함수 선언부 내에서 매개변수를 입출력 매개변수 (in-out parameter)로 선언해야 함
// 입출력 매개변수 사용 전
var myValue = 10

func doubleValue(_ value : Int) -> Int{
    var value = value
    value += value
    return value
}
print("Before function call myValue = \(myValue)")              // 10
print("doubleValue call returns = \(doubleValue(myValue))")     // 20
print("After function call myValue = \(myValue)")               // 10

------------------------------------------------------------------------

// 입출력 매개변수 사용 후
var myValue = 10

func doubleValue(_ value : inout Int) -> Int{
    value += value
    return value
}
print("Before function call myValue = \(myValue)")              // 10
print("doubleValue call returns = \(doubleValue(&myValue))")    // 20
print("After function call myValue = \(myValue)")               // 20

 

 

 

매개변수인 함수

// 매개변수인 함수
func inchesToFeet(_ inches: Float) -> Float{
    inches * 0.0833333
}

let toFeet = inchesToFeet
print(toFeet(10))   // 0.833333
  • 이 기능은 의미 없어 보이지만, 함수 내 매개변수로 함수를 이용할 때 효과적임

 

  • 두 개의 단위 변환 함수를 상수에 할당
// 매개변수로 함수 할당
func inchesToFeet(_ inches: Float) -> Float{
    inches * 0.0833333
}

func inchesToYards(_ inches : Float) -> Float{
    inches * 0.0277778
}

let toFeet = inchesToFeet
let toYards = inchesToYards

 

 

  • 새롭게 만든 함수는 inchesToFeet 함수 타입과 inchesToYards 함수의 타입 모두 일치하는 함수 타입과 함께 변환할 값을 매개변수로 받음
  • 함수의 데이터 타입은 (Float) → Float
func outputConversion(_ converterFunc : (Float) -> Float, value : Float){
    let result = converterFunc(value)
    print("Result of conversion is \(result)")
}

outputConversion(toFeet, value: 10)     // Result of conversion is 0.833333
outputConversion(toYards, value: 10)    // Result of conversion is 0.277778

 

 

 

클로저 표현식

  • 독립적인 코드 블록
  • 클로저 표현식을 선언하고 그것을 sayHello라는 이름의 상수를 할당한 다음에 상수 참조를 통해 함수 호출
// 클로저 표현식
let sayHello = {print("Hello")}
sayHello()  // Hello
{(매개변수 이름 : 매개변수 타입, ... ) -> 반환타입 in 
	// 클로저 표현식 코드
}

// 두 개의 정수를 받아 하나의 정수를 결과 반환
let multiply = {(_ val1: Int, _ val2 : Int) -> Int in
        return val1 * val2
}

let result = multiply(10, 20)
print(result)   // 200
  • 함수를 선언할 때와 비슷하지만, 클로저 표현식은 이름을 갖지 않음
  • 매개변수와 반환 타입은 괄호 안에 포함되며, 클로저 표현식 코드의 시작을 가리키기 위해 in 키워드 사용
  • 함수는 이름이 있는 클로저 표현식
  • 클로저 표현식은 비동기 메서드 호출에 대한 완료 핸들러를 선언할 때 종종 사용됨
  • 어떤 작업을 백그라운드에서 작업하게 해서 애플리케이션이 다른 작업을 계속할 수 있도록 운영체제에게 요청해야 하는 경우가 종종 생김
  • 이런 경우 시스템이 애플리케이션에게 작업이 완료된 것을 알리고 작업(메서드)를 호출할 때 선언했던 완료 핸들러를 호출하여 결과 반환
  • 완료 핸들러에 대한 코드는 주로 클로저 표현식 형태로 구현
eventstore.requestAccess(to: .reminder, completion: {(granted: Bool, error : Error?) -> Void in
    if !granted{
        print(error!.localizedDescription)
    }
})

 

 

 

클로저

  • 함수나 클로저 표현식 같은 독립적인 코드 블록과 코드 블록 주변에 있는 하나 이상의 변수가 결합된 것
// 클로저
func functionA() -> () -> Int {
    var counter = 0
    func functionB() -> Int {
        return counter + 10
    }
    return functionB
}
let myClosure = functionA()
let result = myClosure()    // 10
  • functionA는 functionB라는 이름의 함수를 반환
  • functionB는 functionB의 내부 영역 밖에 선언된 counter 변수에 의존하기 때문에 functionA는 클로저를 반환하고 있음
  • functionB는 counter 변수를 잡고 있다(captured), 또는 가두고 있다 (closed over) → 클로저

'Swift' 카테고리의 다른 글

Swift - 6. 서브 클래싱과 익스텐션 개요  (0) 2023.12.28
Swift - 5. 객체 지향 프로그래밍 기초  (0) 2023.12.27
Swift - 3. 제어 흐름  (0) 2023.12.26
Swift - 2. 연산자와 표현식  (0) 2023.12.24
Swift - 1. 데이터 타입  (0) 2023.12.24