iOS Swift

iOS Swift Guard문, 함수

Taram 2023. 10. 15. 22:15

※이 iOS 카테고리의 글 들은 학교 강의와 과제를 기반으로 작성한 것입니다.※
※Window환경에서 작업하기 때문에 Online Compiler를 사용하는 점 참고 부탁드립니다.※


이번 포스트에서는 Swift의 Guard문과 함수의 몇가지에 대해 더 알아보겠습니다.

  • Guard 문
    1. Guard 문
        먼저 기능을 알아야 하겠죠? guard문은 조건식이 "거짓"이면 실행합니다.
        그리고 기본적으로 특정 조건에 맞지 않을 경우 현재의 함수나 반복문에서 빠져나갈 수 있도록
        조기출구(early Exit) 전략을 제공합니다.
        추가적으로 표현식이 거짓(false)라면 수행될 else 코드를 꼭 작성해주셔야합니다.
        바로 guard문 문법부터 알려드리겠습니다.
guard <불리언 표현식> else {
// 표현식이 거짓일 경우에 실행될 코드
<코드 블록을 빠져 나갈 구문(return, break, continue 등)>
}
// 표현식이 참일 경우에 실행되는 코드

         여기서 <불리언 표현식>이 거짓일 경우 else 뒤에 오는 구문이 실행 됩니다. 즉, if문으로 생각하면 if문 조건의 반대가 되는 것을 적어주는 것이죠. 그리고 출구 구문을 꼭 적어주어 코드 블록을 빠져나가도록 지정해주어야 합니다. 그렇지 않으면 while을 사용 시 무한 루프가 돌 수도 있고 실행이 코드 안에서 잠식 되버리기 때문이죠.

   2. guard ~ let문
        guard ~ let문은 guard문과 비슷하다고 생각하셔도 무방합니다. guard와 같이 함수 뿐만 아니라 특정 블록 내부에만 존재한다면 사용이 가능합니다. 여기서 알아야 할 점은 함수 내부에서 사용할 시 대게 return을 써서 해당 함수를 조기 출구 용도로 사용합니다. 
       
추가적으로 실무에서 옵셔널 바인딩으로 인해 guard ~ let문을 사용하면 다중 루프가 없는 가독성이 좋은 코드로 만들 수 있습니다. guard ~ let을 이용해 옵셔널 바인딩을 어떻게 하는지 예제를 통해 알려드리겠습니다.

func ABCDEFG(value: Double?) {
guard let a = value else {//조건식이 거짓이면 nil 출력
print("nil")
return //return으로 조기탈출
}
print(a*10.9) //조건식이 참일 때 실행, a 변수를 guard문 밖인 블럭에서도 사용가능
}
ABCDEFG(value: 3) //32.7
ABCDEFG(value: nil) //nil
ABCDEFG(value: 10) //109.0

위 코드를 보시면 value가 nil(값이 없음)일 경우 nil을 출력하고 return으로 빠져나옵니다. 그렇지 않으면 guard문 밖의 print(a*10.9)를 실행하죠.
1) 1번째 함수를 보시면 value에 3을 전달되어 nil이 아니기 때문에 guard문을 건너뛰고 연산하여 32.7이 출력됩니다.

2) 반대로 2번째 함수는 value에 nil이 전달되기 때문에 guard문이 실행되어 nil을 출력하고 블럭을 빠져나오는 것이죠.
3) 추가적으로 a 변수는 guard문에서 선언되고 활용되었는데 guard문 밖의 블럭에서도 활용할 수 있습니다.
이렇게 guard문으로 옵셔널 바인딩과 조기탈출의 활용법을 보여주는 예제가 되겠습니다.

     3. Default Argument(디폴트 매개변수)
         디폴트 매개변수는 매개변수로 넘길 값이 없는 경우 사용하는 값입니다. 즉 말 그대로 기본적 매개변수 인 것이죠.
         예제를 통해 확인해봅시다.

func sayHello(tall: Int = 180, name: String ) -> String {
return ("\(name), 당신의 키는 \(tall)")
}

var message = sayHello(tall:10, name: "Taram")
//Taram, 당신의 키는 10

var message = sayHello(name : "Taram")
print(message) //Taram, 당신의 키는 180

 위 예제에서 함수 sayHello를 선언하고 tall을 Int형으로 180, name은 String형으로 값을 지정하지 않았습니다.
실행 결과를 보면 1번째 함수는 Taram, 당신의 키는 10으로 매개변수로 넘긴 값이 그대로 출력되었습니다.
하지만 2번째 함수는 어떨까요? 이름만 Taram이라는 매개변수로 넘기고 tall의 값은 지정하지 않았습니다. 하지만 디폴트 매개변수로 인해 지정해놓은 180이 출력되는 것을 확인할 수 있죠.
이렇게 전달하는 값이 없는 경우 기본적으로 사용되는 값임을 확인할 수 있습니다. 


  • 함수
    1. 함수로부터 여러 개의 결과 반환하기
        예전 포스트에서 튜플(Tuple)이란 것을 배웠습니다. 함수는 여러가지 결과 값들로 튜플(Tuple)로 감싸서 반환할 수 있기 때문에 여러 개의 결과를 반환할 수 있습니다. 예제를 먼저 확인해볼까요?
func converter(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)
}
var lengthTuple = converter(length:10)
print(lengthTuple) //(yards: 0.277778, centimeters: 25.4, meters: 0.254)
print(lengthTuple.yards) //0.0277778
print(lengthTuple.centimeters) //25.4
print(lengthTuple.meters) //0.254

1️⃣ converter 함수:
length라는 매개변수로 받은 길이(Float) 값을 이용하여 야드(yards), 센티미터(centimeters), 미터(meters)로 변환합니다.
각각의 변환된 값들을 튜플로 반환합니다.

2️⃣ 변수 lengthTuple:
converter 함수를 호출하고 반환된 튜플 값을 저장합니다.
입력된 길이인 10에 대한 변환이 수행되어 (yards: 0.277778, centimeters: 25.4, meters: 0.254)라는 튜플 값이 할당됩니다.

3️⃣ 출력문:
print(lengthTuple)은 튜플 전체 값을 출력합니다.
(yards: 0.277778, centimeters:25 .4 , meters :0 .254 )
print(lengthTuple.yards)는 튜플 내부의 야드(yards) 값만 출력합니다.
0 .0277778
print(lengthTuple.centimeters)는 튜플 내부의 센티미터(centimeters) 값만 출력합니다.
25 .4
print(lengthTuple.meters)는 튜플 내부의 미터(meters) 값만 출력합니다.
0 .254
이처럼 주어진 길이 값을 야드(yards), 센티미터(centimeters), 미터(meters)로 변환하여 반환하고 해당 결과값을 변환하여 튜플을 출력하는 함수의 기능을 확인 해 볼 수 있습니다.

   2. 2개의 정수를 입력받아 가감제 리턴
      추가적으로 2개의 정수로 사칙연산, 나머지, 소수점 셋째 자리에서 반올림까지 수행하는 코드도 알아보겠습니다.

import Foundation //String구조체를 사용하기위해 선언
func sss(x: Int, y: Int) -> (sum: Int, sub: Int, mul: Int, divResult: Double, modResult:Int) {
    let sum = x + y
    let sub = x - y
    let mul = x * y
    let divResult = Double(x) / Double(y)
    let modResult = x % y
    
    return (sum, sub, mul, divResult, modResult)
}

var result = sss(x: 10, y: 3)
print(result.sum) //13, 덧셈
print(result.sub) //7, 뺄셈
print(result.mul) //30, 곱셈
print(String(format:"%.2f",result.divResult)) // 소수점 둘째 자리까지 출력, 3.33, 나누기
print(result.modResult) //1, 나머지
print(type(of:sss)) //(Int, Int) -> (sum: Int, sub: Int, mul: Int, divResult: Double, modResult: Int)

이 코드를 살펴보면 sss함수는 사칙연산과 나머지, 반환값으로 각각 돌려주는 기능을 수행합니다. 함수를 호출하며 x와 y의 값을 각각 10과 3으로 매개변수로 넘겨주고 기능을 수행합니다. 그리고 출력 결과를 확인해보면 각각 튜플에 맞는 값들이 들어가 있고 소수점 둘째 자리까지 출력하는 모습도 확인할 수 있습니다.

   3. 가변 매개변수
        가변 매개변수는 매개변수에 몇 개의 매개변수가 들어와도 상관없는 기능을 지원합니다. 바로 예제로 들어갈게요.

func displaySumOfIntegers(numbers: Int...) {
    var sum: Int = 0 //합계를 저장할 sum 선언
    
    for number in numbers { 
        sum += number
    }
    
    print("Sum of integers:", sum)
}

displaySumOfIntegers(numbers: 1, 2, 3, 4) //Sum of integers: 10
displaySumOfIntegers(numbers: 10, 20, 30) //Sum of integers: 60

1️⃣ displaySumOfIntegers 함수:
- numbers라는 가변 인자(Int...) 매개변수로 정수 값들을 받습니다.
- 변수 'sum'을 초기값 "0"으로 선언합니다.
-  반복문(for-in)을 사용하여 numbers 배열 내 모든 요소들을 순회하면서 각 요소를 합계 변수 'sum'에 더합니다.
-  "Sum of integers:"와 함께 계산된 합계(sum)가 출력됩니다.

2️⃣ 함수 호출:
-  displaySumOfIntegers(numbers: 1, 2, 3, 4)은 숫자인 "1", "2", "3", "4" 네 개를 인자로 전달하여 함수를 호출합니다. 이 경우에는 숫자들의 합인 "10"이 출력됩니다.
-  displaySumOfIntegers(numbers: 10, 20, 30)은 숫자인 "10", "20", "30" 세 개를 인자로 전달하여 함수를 호출합니다. 이 경우에는 숫자들의 합인 "60"이 출력됩니다.

   4. inout
       inout을 사용하면 call by address를 구현할 수 있습니다. 주소를 불러온다는 뜻이죠. C언어를 사용해보신 분이라면 주소를 사용할 땐 꼭 &를 쓰는 것을 기억하실 겁니다. 즉 변수의 주소 값을 불러와서 주소에 값을 저장하는 것입니다. 주소에 저장한다면 그 이후의 값은 항상 바뀐 값으로 유지됩니다. 예제를 먼저 보실까요?

//Swift 3이후
var myValue = 10
func doubleValue (value: inout Int) -> Int {
value += value
return(value)
}
print(myValue) //10
print(doubleValue(value : &myValue)) //20
print(myValue) //20

1️⃣ 변수 선언:
- myValue라는 변수를 정수 값 "10"으로 초기화합니다.

2️⃣ doubleValue 함수:
-  value라는 inout 매개변수로 정수 값을 받습니다. 이렇게 선언된 매개변수는 값이 아닌 참조로 전달되며, 함수 내에서 값을 변경할 수 있습니다.
-  주어진 값에 자기 자신을 더하여 두 배로 만듭니다.
-  변경된 값을 반환합니다.
3️⃣ 함수 호출 및 출력:
-  print(myValue)은 초기값인 "10"을 출력합니다.
-  print(doubleValue(value: &myValue))은 doubleValue 함수를 호출하고, 매개변수에 변수 'myValue'의 참조(&)를 전달합니다. 따라서 'myValue'의 값이 함수 내에서 변경되고, 그 결과인 "20"을 출력합니다.
-  마지막으로 print(myValue)은 변경된 값인 "20"을 출력합니다.


  • 뤼튼에게 질문하는 추가 과제
    질문 : iOS 테이블뷰에서 많이 사용하는 메서드를 많이 사용하는 순서대로 나열하고 예를 들어 기능을 설명하고, 전체 메서드 이름과 메서드 자료형을 알려줘.

    답 : 
    1. numberOfSections(in tableView: UITableView) -> Int: 테이블뷰에 표시할 섹션의 개수를 반환하는 메서드입니다. tableView 인자는 해당 테이블뷰 객체를 의미하며, 반환값은 섹션의 개수(Int)입니다.

    2. tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int: 주어진 섹션에 속하는 행(row)의 개수를 반환하는 메서드입니다. tableView 인자는 해당 테이블뷰 객체를 의미하며, section 인자는 섹션의 인덱스(Int)입니다. 반환값은 해당 섹션의 행 개수(Int)입니다.

    3. tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell: 주어진 인덱스 경로(IndexPath)에 대한 셀(Cell)을 반환하는 메서드입니다. tableView 인자는 해당 테이블뷰 객체를 의미하며, indexPath 인자는 셀 위치에 대한 정보가 담긴 IndexPath 객체입니다. 반환값은 해당 위치에 대한 UITableViewCell 객체입니다.

    4. (선택적인 메서드)tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath): 사용자가 주어진 위치(IndexPath)의 셀을 선택했을 때 호출되는 메서드입니다. 선택된 셀에 대한 추가 작업을 수행할 수 있습니다.

    5. (선택적인 메서드)tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat: 주어진 위치(IndexPath)의 셀 높이 값을 반환하는 메서드입니다. 기본적으로 자동으로 계산되지만 필요에 따라 커스텀 높이 값을 지정할 수 있습니다.

    6. (선택적인 메서드)sectionIndexTitles(for tableView: UITableView) -> [String]?`: 선택 가능한 섹션 인덱스 목록을 문자열 배열로 반환하는 메소드 입니다.

    7.(선택적인메소트)sectionForSectionIndexTitle(title:String , at index:Int)->Int?
    :사용자가 오른쪽 상단에서 제공된 탭들 중 하나 탭했을 때 그제목과 관련된 섹션이 어디있나 판단해주기 위해서 구현합니다.

    8.(선택적인메소트)titleForHeaderInSection(section:Int)->String?
    :각각의 section마다 header title 붙여줄거면 이메소트 사용

    9.(선택적인메소트)titleForFooterInSection(section:Int)->String?
    :각각의 section마다 footer title 붙여줄거면 이메소트 사용

    10.(선택적인메소트)
    func tableView(_ tableview:UITableView,
    commit editingStyle:UITableView.CellEditingStyle,
    forRowAt indexPath:NSIndexPath)
    :셀 삭제 버튼 클릭시 실행됩니다.

    11.(필수옵션이지만 기본구현도 되어있음)
    func numberOfSections(in tableview:UITableView)->Int
    :tableview안에서 몇개 구분짓고 싶으면 이함수안에서 그 숫자 리턴해야 합니다.

    12.(필수옵션이지만 기본구현도 되어있음)
    func tableView(tableView:UITableView,
    cellForRowAtIndexPath
    indexPath:NSIndexPath)->UITableViewCell
    :tableview안에서 각각 row마다 cell 하나씩 만들기위해 호출됩니다.

    13.(필수옵션이지만 기본구현도 되어있음)
    func tableView(tableView:UITableView,
    numberOfRowsInSection section:Int)->Int
    :tableview안에서 몇개 row 생성할건지 리턴해야 합니다.

    위와 같은 순서로 일반적으로 iOS에서 Table View와 관련하여 많이 사용되는 함수들이 나열됩니다.