[์ฝ๋๋ฒ ์ด์คUI] iOS ์ ๋ฌธ ๊ฐ์ธ๊ณผ์ _๊ฐ๋จํ ๊ณ์ฐ๊ธฐ ์ฑ ๋ง๋ค๊ธฐ 4 ~ 6๋จ๊ณ
Lev.4 ์ซ์๋ฒํผ๊ณผ ์ฐ์ฐ ๋ฒํผ์ ์์ ๊ตฌ๋ถํ๊ธฐ
๋ฐ์ํ ์ค๋ฅ
์ค๋ฅ ์ค๋ช
Thread 1: Fatal error: Can't form a Character from a String containing more than one extended grapheme cluster
์ด ์ค๋ฅ๋ ์ฃผ์ด์ง ๋ฌธ์์ด์ด ํ๋์ Character๋ก ํํ๋ ์ ์์ ๋ ๋ฐ์ํ๋ค.
Swift์์ Character๋ ํ๋์ ํ์ฅ๋ ์๋ชจ ํด๋ฌ์คํฐ(Extended Grapheme Cluster)๋ก ์ ์๋๋ค.
ํ์ฅ๋ ์๋ชจ ํด๋ฌ์คํฐ๋ ํ๋์ ๋ฌธ์๋ก ์ธ์๋๋ ๋จ์ผ ์ ๋์ฝ๋ ์ํ์ค๋ฅผ ์๋ฏธํ๋ค.
์ฆ, “AC”๊ฐ ํ๋์ ๋ฌธ์๊ฐ ์๋๋ผ ๋ฐ์ํ ์ค๋ฅ์๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
buttonNums ๋ฌธ์์ด ๋ฐฐ์ด์ ์๋ ์์๋ค์ ๋ฐ๋ณต๋ฌธ์ ํตํด
์ ์๋ก ๋ณํ์ด ๋๋ฉด ์์์ ๋ฐ๊ฟ์ฃผ๊ณ , ์ ์๋ก ๋ณํ์ด ๋์ง ์๋๋ค๋ฉด(nil)
์์์ ๋ณ๊ฒฝํด์ฃผ๋ ์กฐ๊ฑด๋ฌธ ์์ฑ.
์ ์ถ ์ฝ๋
import UIKit
import SnapKit
class ViewController: UIViewController {
var viewNum = 0
var numLabel = UILabel()
let buttonNums = ["7", "8", "9", "+",
"4", "5", "6", "-",
"1", "2", "3", "×",
"AC", "0", "=", "÷"]
//horizontalStackView ํด๋ก์ ์ฌ์ฉ
private func horizontalStackView(_ buttons: [UIButton])-> UIStackView {
let stackView = UIStackView(arrangedSubviews: buttons)
stackView.axis = .horizontal
stackView.backgroundColor = .black
stackView.spacing = 10
stackView.distribution = .fillEqually
return stackView
}
var verticalStackView: UIStackView = {
let stackView = UIStackView()
stackView.axis = .vertical
stackView.backgroundColor = .black
stackView.spacing = 10
stackView.distribution = .fillEqually
return stackView
}()
//๋ฒํผ ํ์ค์ ๋ง๋ค์ด์ horizontalStackView์ ๋ฃ์ด์ฃผ๋ ํจ์
private func makeNumButton(buttonNums: [String]) {
var buttonArray: [UIButton] = []
for num in buttonNums {
let button = UIButton()
if Int(num) != nil {
button.backgroundColor = UIColor(red: 58/255, green: 58/255, blue: 58/255, alpha: 1.0)
} else{
button.backgroundColor = .orange
}
button.setTitle(num, for: .normal)
button.titleLabel?.font = .boldSystemFont(ofSize: 30)
button.layer.cornerRadius = 40
buttonArray.append(button)
if buttonArray.count == 4 {
verticalStackView.addArrangedSubview(horizontalStackView(buttonArray))
buttonArray = []
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
makeNumButton(buttonNums: buttonNums)
}
func configureUI(){
//์์ฑ
view.backgroundColor = .black
numLabel.backgroundColor = .black
numLabel.textColor = .white
numLabel.text = "\(viewNum)"
numLabel.textAlignment = .right
numLabel.font = .boldSystemFont(ofSize: 60)
//view์
[numLabel, verticalStackView].forEach{view.addSubview($0)}
//AutoLayout
numLabel.snp.makeConstraints {
$0.leading.trailing.equalToSuperview().inset(30)
$0.top.equalToSuperview().offset(200)
}
verticalStackView.snp.makeConstraints {
$0.height.equalTo(350)
$0.width.equalTo(350)
$0.top.equalTo(numLabel.snp.bottom).offset(60)
$0.centerX.equalToSuperview()
}
}
}
#Preview{
let preview = ViewController()
return preview
}
lev.5 ๋ ๋ฒํผ์ ์ํ์ผ๋ก ๋ง๋ค์ด์ฃผ๋ ๊ฒ์ผ๋ก
button.layer.cornerRadius = 40
์ด๋ฏธ ์์ ๋จ๊ณ์์ ํด๊ฒฐ ์๋ฃ.
Lev.6 ๋ฒํผ์ ํด๋ฆญํ๋ฉด ๋ผ๋ฒจ์ ํ์๋๊ฒ ํ๊ธฐ_์ซ์๊ฐ 0์ผ๋ก ์์ํ์ง ์๊ฒ ํ๊ธฐ.
๋ฒํผ์ ๋๋ ์ ๋ ํด๋น ๋ฒํผ์ ํ์ดํ num์
์ด๋ป๊ฒ label.text์ ๋ฃ๋์ง์ ๋ํ ๊ณ ๋ฏผ์ด ์ ๋ง ๋ง์๋ค.
๋ฒํผ์ด ๋ง๊ธฐ ๋๋ฌธ์ numButtonTapped() ํจ์๋ฅผ ์๋ก ๋ง๋ค์ด์
๋ฒํผ์ด ๋๋ ธ์ ๋ ๊ฐ๊ฐ์ ๋ฒํผ์ ํ์ดํ์ ๋ผ๋ฒจ์ ๋ฃ๊ธฐ๋ก ๊ฒฐ์ ํ๋ค.
์ด ๊ณผ์ ์ค์์ ๋ค๋ฅธ ๋ถ๋ค๊ป ์ง๋ฌธํ๋ฉด์ ์ด ํจ์์ ๋งค๊ฐ๋ณ์๋ก UIButton์ ๋ฐ๊ณ
currntTitle์ ์ฌ์ฉํด ๊ฐ์ ์ป์ ์ ์๋ ํํธ๋ฅผ ์ป์๋ค.
String? ํ์ ์ผ๋ก ์ฌ์ฉ ์ ์ธ๋ฉํ์ ํด์ฃผ์ด์ผ ํ๋ค.
๋ฐ์ํ ์ค๋ฅ
์ฌ๊ธฐ์ numButtonTapped(sender: UIButton) ํจ์์์ UIButton์ด ๋งค๊ฐ๋ณ์๋ก
์ด๋ป๊ฒ ์ ๋ฌ ๋ฐ์ ์ ์๋์ง ์๋ฌธ์ด ์๊ฒผ๋ค.
numButtonTapped(sender: UIButton) ํจ์์์ UIButton์
makeNumButton(buttonNums: [String]) ํจ์ ๋ด์์ ์์ฑ๋ ๋ฒํผ๋ค์ด
addTarget ๋ฉ์๋๋ฅผ ํตํด ํธ์ถ๋์์ ๋ ์ ๋ฌ๋๋ค.
addTarget ๋ฉ์๋๋ ๋ฒํผ์ด ํฐ์น๋๋ฉด ํด๋น ๋ฒํผ ๊ฐ์ฒด(sender)๋ฅผ
numButtonTapped ํจ์์ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌํ๋ค.
ํ์ง๋ง, ์ด๋ ๊ฒ ์์ฑํ ์ ์ฑ์ด ์๋์ด ๋์ง ์์๋ค.
viewNum์ numLable์์ 0์ผ๋ก ๋ณด์ด๊ธฐ ์ํด
์ ์ญ ๋ณ์๋ก ์ด๊ธฐ๊ฐ์ "0"์ผ๋ก ์ธํ ํ์๋ค.
์ด viewNum์ ์ ๋ ฅ๋ ๋ฌธ์์ด์ ์ฒซ๋ฒ์งธ ์ธ๋ฑ์ค๊ฐ "0"์ด ์๋๋ผ๋ฉด
์ฌ์ฉ์๋ก๋ถํฐ ์ ๋ ฅ๋ฐ์ userInput์ ์ถ๊ฐํด์ฃผ๊ณ ,
"0"์ด๋ผ๋ฉด ์ฒซ๋ฒ์งธ ์ธ๋ฑ์ค๋ฅผ ์ ๊ฑฐํด์ฃผ๊ณ userInput์ ์ถ๊ฐํด์คฌ์ด์ผ ํ๋ค.
ํ์ง๋ง ๊ทธ ๋ถ๋ถ์ด ๋น ์ ธ์, "0"์ผ ๋ ์ด๋ฅผ ์ ๊ฑฐํ๋ nil๋ก ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ ๊ฒ ๊ฐ๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
์ด๋ ๊ฒ ์์ ํ๋ ์๋์ด ๋์๋ค.
๊ทธ๋ฆฌ๊ณ ๊ตณ์ด ์ธ๋ฑ์ค๋ก ์ ๊ทผํ์ง ์์๋ ๋น๊ต๋ฅผ ์ ์์๋ค.
์ ์ถ ์ฝ๋
//
// ViewController.swift
// calculatorApp
//
// Created by ahnzihyeon on 6/26/24.
//
import UIKit
import SnapKit
class ViewController: UIViewController {
var viewNum = "0"
var numLabel = UILabel()
let buttonNums = ["7", "8", "9", "+",
"4", "5", "6", "-",
"1", "2", "3", "×",
"AC", "0", "=", "÷"]
//horizontalStackView ํด๋ก์ ์ฌ์ฉ
private func horizontalStackView(_ buttons: [UIButton])-> UIStackView {
let stackView = UIStackView(arrangedSubviews: buttons)
stackView.axis = .horizontal
stackView.backgroundColor = .black
stackView.spacing = 10
stackView.distribution = .fillEqually
return stackView
}
var verticalStackView: UIStackView = {
let stackView = UIStackView()
stackView.axis = .vertical
stackView.backgroundColor = .black
stackView.spacing = 10
stackView.distribution = .fillEqually
return stackView
}()
//๋ฒํผ ํ์ค์ ๋ง๋ค์ด์ horizontalStackView์ ๋ฃ์ด์ฃผ๋ ํจ์
private func makeNumButton(buttonNums: [String]) {
var buttonArray: [UIButton] = []
for num in buttonNums {
let button = UIButton()
if Int(num) != nil {
button.backgroundColor = UIColor(red: 58/255, green: 58/255, blue: 58/255, alpha: 1.0)
} else{
button.backgroundColor = .orange
}
button.setTitle(num, for: .normal)
button.titleLabel?.font = .boldSystemFont(ofSize: 30)
button.layer.cornerRadius = 40
buttonArray.append(button)
if buttonArray.count == 4 {
verticalStackView.addArrangedSubview(horizontalStackView(buttonArray))
buttonArray = []
}
button.addTarget(self, action: #selector(numButtonTapped), for: .touchDown)
}
}
@objc
private func numButtonTapped(sender: UIButton) {
var userInput = sender.currentTitle!
if numLabel.text == "0" {
viewNum.removeFirst()
viewNum += userInput
} else {
viewNum += userInput
}
numLabel.text = viewNum
}
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
makeNumButton(buttonNums: buttonNums)
}
func configureUI(){
//์์ฑ
view.backgroundColor = .black
numLabel.text = "0"
numLabel.backgroundColor = .black
numLabel.textColor = .white
numLabel.textAlignment = .right
numLabel.font = .boldSystemFont(ofSize: 60)
numLabel.adjustsFontSizeToFitWidth = true //label ์ฌ์ด์ฆ์ ๋ง๊ฒ ํฐํธ ํฌ๊ธฐ ์๋ ์กฐ์
//view์
[numLabel, verticalStackView].forEach{view.addSubview($0)}
//AutoLayout
numLabel.snp.makeConstraints {
$0.leading.trailing.equalToSuperview().inset(30)
$0.top.equalToSuperview().offset(200)
}
verticalStackView.snp.makeConstraints {
$0.height.equalTo(350)
$0.width.equalTo(350)
$0.top.equalTo(numLabel.snp.bottom).offset(60)
$0.centerX.equalToSuperview()
}
}
}
#Preview{
let preview = ViewController()
return preview
}