이 포스트는 한성현 교수님의 iOS 프로그래밍 기초 수업을 듣고 작성되었습니다.
오늘은 3 주 동안 만들어오던 BMI 계산기 앱을 완성해 보겠습니다.
먼저, 들어가기 전에 오토 레이아웃에 대해 알아 보며 시작하겠습니다.
# Auto LayOut
이는 iOS 및 macOS 앱 개발에서 사용되는 레이아웃 시스템으로,
다양한 화면 크기와 해상도에 적응할 수 있도록 UI 요소의 위치와 크기를 자동으로 조정하는 기능입니다.
이의 특징으로는
1. 제약 조건(Constraints): 오토 레이아웃은 UI 요소 간의 관계를 정의하는 제약 조건을 사용하여 요소의 위치와 크기를 결정합니다.
예를 들어, 한 요소가 다른 요소의 위, 아래, 왼쪽, 오른쪽에 얼마나 떨어져 있는지를 설정할 수 있습니다.
2. 유연성: 다양한 화면 크기와 방향에 맞춰 UI가 자동으로 조정되므로, 여러 기기에서 일관된 사용자 경험을 제공합니다.
3. 동적인 크기: UI 요소는 콘텐츠의 크기에 따라 자동으로 조정될 수 있어, 다양한 텍스트 길이나 이미지 크기에 대응할 수 있습니다.
4 .성능 최적화: 오토 레이아웃은 레이아웃 계산을 최적화하여 성능을 개선합니다. 필요하지 않은 경우 레이아웃 업데이트를 최소화합니다.
네 가지로 정리해 볼 수 있습니다.
그렇다면, xcode 에서 오토 레이아웃을 어떻게 지정할 수 있을까요?
제약 조건 추가를 통해 진행할 수 있습니다.
UI 요소를 선택한 후, 제약 조건 버튼 사용하여 지정할 수 있습니다.
오른쪽 하단의 'Add New Constraints' 버튼(사각형 아이콘)을 클릭하여, 요소의 상하좌우 간격을 설정할 수 있습니다. 원하는 값을 입력하고 'Add Constraints' 버튼을 클릭합니다.
# 제약 조건 추가
이제 앱에 적용을 해 보겠습니다.
이렇게 추가된 것을 확인할 수 있겠죠?
# 앱 아이콘 지정
마지막으로 아이콘 변경을 해 보겠습니다.
저는 IconFinder 에서 이미지를 하나 가져와서 1024 픽셀로 크기 조정을 해 준 뒤에,
이렇게 집어 넣었습니다!
시뮬레이터 내에서는 이렇게 되는 것을 확인할 수 있습니당.
# LaunchScreen 구성
런치 스크린은 화면이 로딩되기 전에 잠깐 보이는 화면입니다.
이 화면을 한 번 꾸며 보겠습니다.
이렇게 구성해 보았습니다.
... 잡으려고 했지만 실패했습니다. 저렇게 잠깐 뜨는 부분이 런치 스크린이라고 볼 수 있습니다.
# SketchView
다음은 스케치 뷰를 하나 더 추가해 보겠습니다.
저번에 교수님이 주신 앱 코드들을 훑어볼 때 봤었던 앱 중 하나를 불러와서 제 앱에 붙여 보았습니다.
이렇게 화면을 복사 붙여넣기 해 주고,
코드들도 불러와서 붙였습니다.
그 뒤, 탭 바 컨트롤러와 연결해 준다면
아래 아이콘이 네 개로 변경되면서 Sketch 창에서는 그림을 그릴 수 있는 창이 완성됩니다.
이렇게 BMI 앱을 완성해 보았습니다!
이제는 차차 위 앱을 변형하여 보겠습니다.
# BMI 창
먼저 BMI 를 계산하는 창에 목표 체중을 입력하면 그 무게까지 얼마나 남았는지 알려 주는 기능을 추가하였습니다.
이는
//
// ViewController.swift
// BMI_ycr
//
// Created by 윤채림 on 11/13/24.
//
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var txtHeight: UITextField!
@IBOutlet weak var txtWeight: UITextField!
@IBOutlet weak var lblResult: UILabel!
@IBOutlet weak var goalWeight: UITextField!
@IBOutlet weak var lblWeightDifference: UILabel!
@IBAction func calcBmi(_ sender: UIButton) {
if txtHeight.text == "" || txtWeight.text == "" || goalWeight.text == "" {// "" 은 nil 이 아니고 null 로 값이 없는 것을 의미
lblResult.textColor = .red
lblResult.text = "키와 체중을 입력하세요잉!"
lblWeightDifference.text = "목표 체중을 입력하세요잉!"
return
} else {
let weight = Double(txtWeight.text!)!
let height = Double(txtHeight.text!)!
let goalWeight = Double(goalWeight.text!)!
let bmi = weight / (height*height*0.0001) // kg/m*m
let shortenedBmi = String(format: "%.1f", bmi)
var body = ""
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.0, blue: 1.0, alpha: 1.0)
body = "정상"
} else {
color = UIColor(displayP3Red: 0.0, green: 1.0, blue: 0.0, alpha: 1.0)
body = "저체중"
}
// print("BMI:\(shortenedBmi), 판정:\(body)")
lblResult.backgroundColor = color
lblResult.clipsToBounds = true
lblResult.layer.cornerRadius = 10
lblResult.textColor = .white
lblResult.text = "BMI: \(shortenedBmi), 판정: \(body)"
let weightDifference = goalWeight - weight
if weightDifference > 0 {
lblWeightDifference.text = "목표 체중까지 \(String(format: "%.1f", weightDifference)) kg 남았어요잉..."
} else if weightDifference < 0 {
lblWeightDifference.text = "\(String(format: "%.1f", -weightDifference)) kg 초과했어요잉 ㅠㅠ "
} else {
lblWeightDifference.text = "목표 체중에 도달했어요잉!"
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
lblWeightDifference.text = "" // 초기화
}
}
goalWeight 와 WeightDiffference 를 받아와서 코드를 돌릴 수 있게 구현하였습니다.
# Video 창
play button 을 눌렀을 때 밑에 있는 라벨이 APT 시작! 😍 이라는 멘트가 띄워지게 코드를 수정하였습니다.
//
// VideoViewController.swift
// BMI_ycr
//
// Created by 윤채림 on 11/27/24.
//
import UIKit
import AVKit
class VideoViewController: UIViewController {
@IBOutlet weak var lblMessage: UILabel!
@IBAction func playVideo(_ sender: UIButton) {
guard let videoPath = Bundle.main.path(forResource: "APT", ofType: "mp4") else{ return }
let videoURL = URL(filePath: videoPath)
let player1 = AVPlayer(url: videoURL)
let playerController = AVPlayerViewController()
playerController.player = player1
self.present(playerController, animated: true) {
player1.play()
self.lblMessage.text = "APT 시작! 😍"
}
}
override func viewDidLoad() {
super.viewDidLoad()
lblMessage.text = ""
}
}
# web 창
여기는 원래 티스토리와 유튜브 링크만 불러올 수 있도록 구현되어있었는데,
추가적으로 네이버까지 불러오도록 코드를 수정하였습니다.
//
// WebViewController.swift
// BMI_ycr
//
// Created by 윤채림 on 11/27/24.
//
import UIKit
import WebKit
class WebViewController: UIViewController {
@IBOutlet weak var webView: WKWebView!
@IBAction func goYoutube(_ sender: UIButton) {
guard let url = URL(string: "https://m.youtube.com") else { return }
let request = URLRequest(url: url)
webView.load(request)
}
@IBAction func goNaver(_ sender: UIButton) {
guard let url = URL(string: "http://m.naver.com") else { return }
let request = URLRequest(url: url)
webView.load(request)
}
override func viewDidLoad() {
super.viewDidLoad()
guard let url = URL(string: "https://dbsc0f1a.tistory.com/") else { return }
let request = URLRequest(url: url)
webView.load(request)
}
}
# Sketch 창
마지막으로 스케치 창에는 배경색을 앱 색과 동일하게 만들어 주면 통일감을 맞추어 주며,
앱을 새로 업그레이드 시켰습니다.
앱을 업그레이드 시키기 전 모든 기능을 구현한 코드는 깃허브에 업로드 하였습니다.
'iOS' 카테고리의 다른 글
[iOS] 생성형 AI 및 오픈 API 활용 (0) | 2025.03.05 |
---|---|
[iOS] 클로저 Closure (0) | 2024.12.11 |
[iOS] BMI 계산기 앱 2 (0) | 2024.11.27 |
[iOS] BMI 계산기 앱 (1) | 2024.11.20 |
[iOS] 간단한 앱 구현 (1) | 2024.11.13 |