SA성아 2024. 11. 20. 16:48

오토 레이아웃을 잡아주지 않아서 Issue navigator가 뜸 

오토 레이아웃(Auto Layout) : iOS 앱 개발에서 UI 요소(뷰)의 크기와 위치를 다양한 화면 크기와 방향에 따라 유동적으로 조정할 수 있도록 돕는 레이아웃 시스템

 

 

3개의 아울렛 연결

입력을 받아들이는 2개의 아울렛과 결과를 나타내는 아울렛 1개 연결

 

 

Oulet 3개, Action 1개의 간단한 앱

 

 

cmd + R 후 계산을 누르면 콘솔창에 정상이 뜸 

 

 

text필트에 값을 넣지 않으면 크래시가 나는 소스

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var txtWeight: UITextField!
    @IBOutlet weak var txtHeight: UITextField!
    @IBOutlet weak var lblResult: UILabel!
    @IBAction func calcBmi(_ sender: UIButton) {
        let weight = Double(txtWeight.text!)!
        let height = Double(txtHeight.text!)!
        let bmi = weight / (height*height*0.0001) // kg/m*m
        let shortenedBmi = String(format: "%.1f", bmi)
        var body = ""
        if bmi >= 40 {
            body = "3단계 비만"
        } else if bmi >= 30 && bmi < 40 {
            body = "2단계 비만"
        } else if bmi >= 25 && bmi < 30 {
            body = "1단계 비만"
        } else if bmi >= 18.5 && bmi < 25 {
            body = "정상"
        } else {
            body = "저체중"
        }
        print("BMI:\(shortenedBmi), 판정:\(body)")
        lblResult.text = "BMI:\(shortenedBmi), 판정:\(body)"
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    
}

 

1. txtHeight.text와 txtWeight.text

  • UITextField의 text 속성은 옵셔널(Optional) 타입인 String?입니다.
    즉, 값이 있을 수도 있고 없을 수도 있는 상태를 나타냅니다.
    강제로 옵셔널을 해제하기 위해 !를 사용한 것입니다.
txtHeight.text! // 옵셔널(String?) → String으로 강제 변환

 

2. Double(txtHeight.text!)

  • Double() 생성자는 문자열을 받아 Double로 변환하는데, 이 역시 반환값이 **옵셔널(Optional)**입니다.
    변환이 실패할 경우 nil을 반환하기 때문에, 이를 다시 강제 언래핑한 것입니다.
Double(txtHeight.text!)! // Double? → Double로 강제 변환

 

값을 넣지 않으면 경고문을 띄우게 함

 

소스정렬

cmd + A -> ctrl + I

 

//
//  ViewController.swift
//  BMI_psa
//
//  Created by redmist on 11/13/24.
//

import UIKit

class ViewController: UIViewController {
    // MARK: - 아웃렛 연결
    @IBOutlet weak var txtWeight: UITextField! // 체중 입력 필드
    @IBOutlet weak var txtHeight: UITextField! // 키 입력 필드
    @IBOutlet weak var lblResult: UILabel!     // 결과를 표시할 레이블

    // MARK: - BMI 계산 버튼 액션
    @IBAction func calcBmi(_ sender: UIButton) {
        // 1. 입력값이 비어 있는지 확인
        if txtHeight.text == "" || txtWeight.text == "" {
            lblResult.textColor = .red // 경고 메시지는 빨간색으로 표시
            lblResult.text = "키와 체중을 입력하세요."
            return // 입력값이 없으면 함수 종료
        } else {
            // 2. 입력값을 Double로 변환 (강제 언래핑 사용)
            let weight = Double(txtWeight.text!)! // 체중 값
            let height = Double(txtHeight.text!)! // 키 값

            // 3. BMI 계산 (단위: kg/m²)
            let bmi = weight / (height * height * 0.0001)
            let shortenedBmi = String(format: "%.1f", bmi) // 소수점 한 자리로 포맷

            // 4. BMI 값에 따라 판정 및 색상 결정
            var body = "" // BMI 상태를 저장할 변수
            var color = UIColor.white // 결과 레이블의 배경색 기본값

            if bmi >= 40 {
                color = UIColor(displayP3Red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0) // 빨간색
                body = "3단계 비만"
            } else if bmi >= 30 && bmi < 40 {
                color = UIColor(displayP3Red: 0.7, green: 0.0, blue: 0.0, alpha: 1.0) // 짙은 빨간색
                body = "2단계 비만"
            } else if bmi >= 25 && bmi < 30 {
                color = UIColor(displayP3Red: 0.4, green: 0.0, blue: 0.0, alpha: 1.0) // 어두운 빨간색
                body = "1단계 비만"
            } else if bmi >= 18.5 && bmi < 25 {
                color = UIColor(displayP3Red: 0.0, green: 0.2, blue: 0.7, alpha: 1.0) // 파란색
                body = "정상"
            } else {
                color = UIColor(displayP3Red: 0.0, green: 0.9, blue: 0.0, alpha: 1.0) // 초록색
                body = "저체중"
            }

            // 5. 결과 레이블 업데이트
            lblResult.backgroundColor = color // 판정에 따라 배경색 설정
            lblResult.clipsToBounds = true // 코너를 둥글게 하기 위해 필요한 설정
            lblResult.layer.cornerRadius = 7 // 모서리를 둥글게 설정
            lblResult.text = "BMI:\(shortenedBmi), 판정:\(body)" // 결과 텍스트 설정
        }
    }

    // MARK: - 뷰 초기화
    override func viewDidLoad() {
        super.viewDidLoad()
        // 추가적인 초기 설정 코드가 필요한 경우 작성
    }
}

 

Tab Bar Controller

구분 Manual Segue Relationship Segue
용도 특정 이벤트(버튼 클릭 등) 발생 시 화면 전환. 컨테이너 뷰 컨트롤러(예: UITabBarController, UISplitViewController)에서 하위 뷰 컨트롤러 간 관계를 설정.
트리거 방식 코드 또는 인터페이스 빌더에서 직접 호출. 인터페이스 빌더에서 뷰 컨트롤러 간 관계를 설정하며 자동으로 호출.
실행 시점 이벤트(버튼 클릭, 제스처 등)가 발생할 때 코드로 트리거. 앱 실행 시, 관계가 정의된 컨트롤러들이 자동으로 연결됨.
연결 방법 스토리보드에서 control + drag로 두 컨트롤러 연결 후 세그웨이 선택. 컨테이너 컨트롤러와 하위 뷰 컨트롤러를 연결 (스토리보드에서 직접 설정).
구현 방식 performSegue(withIdentifier:sender:) 메서드를 통해 호출 가능. 별도의 호출 코드 없이 컨테이너 뷰 컨트롤러가 자동 관리.
Identifier 필요 여부 필요함 (Segue Identifier로 구분). 필요 없음.
사용 예 버튼 클릭 시 상세 화면으로 이동. UITabBarController의 탭 구성, UISplitViewController의 마스터-디테일 연결.
적합한 시나리오 특정 사용자 액션 기반 화면 전환. 컨테이너 컨트롤러 내 하위 컨트롤러 관계 설정.

출처: iOS 프로그래밍 기초 강의 자료