iOS & Swift 공부 - BMI 계산기 만들기

김영채 (Kevin)·2021년 1월 14일
0

iOS & Swift

목록 보기
25/107


오늘은 위와 같은 BMI Calculator 를 만드는 실습을 진행하였다. 화면 전환 간 Data Passing 이 어떻게 이루어지는지, UISlider 를 어떻게 이용하는지, 그리고 이걸 모두 MVC 디자인 패턴을 적용해 보았다.

우선 스토리보드 인터페이스는 위와 같이 짰다. 좌측이 Calculate View Controller 이고 우측이 Result View Controller 이다.

Calculate View Controller 를 보면 알겠지만, 하나의, 큰 Stack View 안에 여러 요소가 들어가 있다. 이는 Auto Layout 을 나중에 설정하기 편하게 하기 위함이다.

다음은 세그웨이 (Segue) 설정이다. 처음에 세그웨이라길래 응? 했는데 화면 전환을 위한 하나의 방법이다.
Main.storyboard 의 Calculate View Controller 를 우클릭한 상태에서 화면 전환이 되기를 원하는 뷰컨트롤러로 마우스를 끈다. 그렇게 하면 여러가지 세그웨이 형식 중에서 선택을 할 수 있는데 난 Present modally 라는 옵션을 클릭했다. 이 옵션은 화면 전환이 일어났을 때 아예 다른 페이지로 가는 듯한 전환 말고, 아래에서 위로 하나의 모듈?같은 창이 뜰 수 있게 한다.

이렇게 세그웨이를 설정하면 main.storyboard 의 두 뷰컨트롤러 사이에서는 위와 같이 생긴 화살표가 생길 것이다. 이것을 누르고 Attributes Inspector 로 가면 identifier 를 설정을 할 수 있다.

여기서 반드시 Identifier 를 설정하는게 중요한데, 이는 나중에 ViewController.swift 파일에서 performSegue( ) 함수를 실행할 때 필요하기 때문이다. 나는 identifier 를 goToResult 으로 이름을 지었다.

프로젝트 자체도 MVC 디자인 패턴을 적용할 수 있게 바꾸어 주었다. View에는 스토리보드 파일을, Controllers 에는 뷰컨트롤러 파일 2개를, 그리고 Models 에는 BMI 구조체를 선언한 파일 하나와 각종 계산을 위한 함수가 들어가 있는 CalculatorBrain 파일을 생성하였다.

BMI 구조체는 위와 같이 정의하였다.

struct BMI{
    
    let value: Float
    let advice: String
    let color: UIColor
}

value 는 실제 BMI 지수, advice 는 BMI 에 따라 사용자에게 주는 다른 조언들을 위한 변수이고, color 는 BMI 에 따라 다른 background color 를 저장하기 위한 변수다.

다음은 CalculatorBrain.swift 파일이다. 여기서 대부분의 계산이 이루어지는데, 계산이 이루어지는 곳이다 보니 Models 폴더에 넣었다.

여기서는 CalculatorBrain 이라는 구조체를 선언하였고, 기본적인 프로퍼티로 아까 선언한 BMI 구조체 타입이 있다.
메서드로는 크게 4가지가 있다.

1. CalculateBMI(height: Float, weight: Float)

mutating func calculateBMI(height: Float, weight: Float){
        
        let bmiValue = weight / (height*height)
        
        if bmiValue < 18.5{
            bmi = BMI(value: bmiValue, advice: "Eat more pies", color: #colorLiteral(red: 0.4745098054, green: 0.8392156959, blue: 0.9764705896, alpha: 1))
        }
        else if bmiValue < 24.9{
            bmi = BMI(value: bmiValue, advice: "Fit as a fiddle!", color: #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1))
        }
        else{
            bmi = BMI(value: bmiValue, advice: "Eat less pies", color: #colorLiteral(red: 0.9098039269, green: 0.4784313738, blue: 0.6431372762, alpha: 1))
        }
    
    }

뷰컨트롤러에서 CalculatorBrain 인스턴스 생성 후 사용자가 키와 몸무게를 입력하면, BMI 를 계산해야 하는데, 이 계산을 수행하기 위한 함수다.

2. getAdvice() -> String

func getAdvice()->String{
        return bmi?.advice ?? "error in getAdvice()"
        
 }

첫 번째 화면에서 Calculate 를 누르고 두 번째 화면으로 진입하면, BMI 지수에 따라 그에 맞는 적절한? 조언이 나오는데 바로 그걸 실행하기 위한 함수다. 조언은 크게 3가지가 있는데, 위 CalculateBMI( ) 함수를 보면 BMI 지수에 따라 bmi 인스턴스를 다르게 초기화해준다. 여기서 3가지 종류의 조언이 나온다.

3. getColor()->UIColor

func getColor()->UIColor{
        return bmi?.color ?? UIColor.purple
}

BMI 에 따라 다른 background color 를 설정하게 되는데, 이를 설정하기 위한 함수다. 만약 옵셔널을 꺼내는 중 중 에러가 발생하면 일단은 보라색을 return 할 수 있도록 nil coalescing 방법을 사용하였다.

4. getBMIValue()->String

func getBMIValue()->String{
        
        let bmiResult = String(format: "%.1f", bmi?.value ?? 0.0)
        
        return bmiResult
}

이 함수에서는 두 번째 화면에서 텍스트 형태로 BMI 지수를 보여주기 위해 String(format: ) 함수를 사용하였다. String 형식으로 리턴한다.

다음은 CalculateViewController 이다. 기본적으로 @IBOutlet 들을 모두 적절하게 연결시켜주었고, 가장 먼저 CalculatorBrain 타입의 인스턴스 calculatorBrain 을 생성하였다.

그리고 사용자가 heightSlider 와 weightSlider 를 이용해 자신의 키와 몸무게 값을 변경시키면, 그에 맞는 상수에 저장 시킬 수 있도록 하였다.

맨 아래 calculatePressed( ) 함수가 이번 실습의 핵심인데, 여기서 화면 전환 (세그웨이)를 실행한다.

세그웨이 수행 전 우선 처음에 선언한 calculatorBrain 인스턴스의 calculateBMI 함수를 실행한다. 구조체에서 calculateBMI 함수가 있었기 때문에 접근이 가능하며, 매개변수는 사용자가 설정한 height 와 weight 가 되겠다.

그 다음에 performSegue () 를 수행하게 되는데, 매개변수가 2개다. withIdentifier 는 앞 부분에서 설명한 세그웨이의 identifier 이름이다. 나는 goToResult 으로 이름을 지었기 때문에 그대로 쓰면 된다. sender 는 클래스를 말하는데, 현재 있는 클래스를 보내고 싶기 때문에 self 를 넣어주면 된다.

performSegue() 함수가 실행되기 전에 prepare()함수가 실행이 된다. 이 함수는 현재 뷰컨트롤러에게 performSegue()라는 함수가 실행되기 직전임을 알린다.

이 함수 내에서 적절한 값을 대입하여 Data Passing 을 해줘야 한다.

if segue.identifier == "goToResult"
-> 즉, 지금 막 수행되려고 하는 세그웨이의 이름이 goToResult이면~ 이라는 뜻이다.

이 함수 내에서 인스턴스를 만들어야 하는데, 타입은 전환하려는 뷰컨트롤러 (클래스)이다. 이것을 위해서는 segue.destination 을 대입하면 되는데 끝에 as! ResultViewController를 꼭 붙여줘야 downcasting 이 이루어진다. 이 부분을 누락하면 destinationVC 의 타입은 그냥 ResultViewController 의 부모 클래스인 UIViewController 가 된다. 우리는 UIViewController 클래스에 접근하고 싶은게 아니라 ResultViewController 에 접근하고 싶기 때문에 다운캐스팅이 꼭 필요하다.

그 다음에 이제 ResultViewController 내에 있는 변수에 접근이 가능하다. 이 클래스에는 bmiValue, advice, color 변수 3개가 있다.

//CalculateViewController.swift
destinationVC.bmiValue = calculatorBrain.getBMIValue()
destinationVC.advice = calculatorBrain.getAdvice()
destinationVC.color = calculatorBrain.getColor()

prepare( ) 함수 내에서는 위와 같이 각 변수들을 설정해준다. 사용하는 함수는 모두 CalculatorBrain 구조체에 있는 함수들이다.

이렇게 해서 BMI 계산기를 만들어보았다. UISlider 를 이용해서 사용자 입력값을 어떻게 받아오고, 세그웨이 이용을 통해 화면 전환을 어떻게 하는지와, 전환 간 Data Passing 이 이루어지기 위해 prepare()함수를 어떻게 사용하는지도 간단하게 배우게 됐다.

profile
맛있는 iOS 프로그래밍

0개의 댓글