-
Notifications
You must be signed in to change notification settings - Fork 6
[Lv_3,4,5] 수직 스택뷰 구현 및 버튼 UI 개선 #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: mun
Are you sure you want to change the base?
Changes from all commits
98d6f3f
48bbbf5
ebe19fe
d1e69bf
aad553b
11a1e59
2a91c06
932cafa
53cb9e1
53fde2b
c1a2cb4
1dda6f8
6069fbe
445337c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// | ||
// CalculatorModel.swift | ||
// Calculate | ||
// | ||
// Created by mun on 11/21/24. | ||
// | ||
import Foundation | ||
|
||
class CalculatorModel { | ||
|
||
// 계산된 결과 반환 | ||
func calculate(expression: String) -> Int? { | ||
guard isValidExpression(expression) else { return nil } | ||
|
||
let expression = NSExpression(format: expression) | ||
if let result = expression.expressionValue(with: nil, context: nil) as? Int { | ||
return result | ||
} else { | ||
return nil | ||
} | ||
} | ||
|
||
// 수식이 유효한지 확인 | ||
private func isValidExpression(_ text: String) -> Bool { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 수식이 유효한지 확인하는 기능을 Bool을 반환하는 함수로 감싸주신 점 굉장히 좋다고 생각해요! |
||
let textArray = Array(text) | ||
var previousChar: String? | ||
|
||
// 시작 문자가 "-"을 제외한 다른 연산 기호라면 false | ||
if Int(String(textArray.first!)) == nil && textArray.first != "-" { | ||
return false | ||
} | ||
|
||
// 마지막 문자가 연산 기호라면 false | ||
if Int(String(textArray.last!)) == nil { | ||
return false | ||
} | ||
|
||
for char in textArray { | ||
let currentChar = String(char) | ||
|
||
if Int(currentChar) == nil { | ||
// 연산 기호가 연속으로 나오면 false | ||
if currentChar == previousChar { | ||
return false | ||
} | ||
} | ||
} | ||
|
||
return true | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// | ||
// CalculatorView.swift | ||
// Calculate | ||
// | ||
// Created by mun on 11/21/24. | ||
// | ||
|
||
import UIKit | ||
|
||
import SnapKit | ||
|
||
class CalculatorView: UIView { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 별도의 뷰로 작성해 주셨군요! 좋습니다~! |
||
|
||
var label = UILabel() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이러한 라벨, 스택뷰, 버튼데이터는 internal로 노출되어야 할 이유가 있을까요? (저도 몰라서 여쭤봐요!) |
||
var verticalStackView = UIStackView() | ||
|
||
let buttonDatas = [["7", "8", "9", "+"], | ||
["4", "5", "6", "-"], | ||
["1", "2", "3", "*"], | ||
["AC", "0", "=", "/"]] | ||
|
||
override init(frame: CGRect) { | ||
super.init(frame: frame) | ||
configureUI() | ||
configureLayout() | ||
} | ||
|
||
required init?(coder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
|
||
// UI 설정 | ||
private func configureUI() { | ||
self.backgroundColor = .black | ||
[label, verticalStackView].forEach() { | ||
self.addSubview($0) | ||
} | ||
|
||
configureLabel() | ||
configureVerticalStackView() | ||
} | ||
|
||
// label 스타일 설정 | ||
private func configureLabel() { | ||
label.text = "0" | ||
label.textColor = .white | ||
label.textAlignment = .right | ||
label.font = .boldSystemFont(ofSize: 60) | ||
} | ||
|
||
// VerticalStackView 스타일 설정 | ||
private func configureVerticalStackView() { | ||
for i in 0..<4 { | ||
let view = makeHorizontalStackView(i) | ||
verticalStackView.addArrangedSubview(view) | ||
} | ||
|
||
verticalStackView.axis = .vertical | ||
verticalStackView.backgroundColor = .black | ||
verticalStackView.spacing = 10 | ||
verticalStackView.distribution = .fillEqually | ||
} | ||
|
||
// horizontalStackView 생성 | ||
private func makeHorizontalStackView(_ verIndex: Int) -> UIStackView { | ||
let horizontalStackView = UIStackView() | ||
|
||
horizontalStackView.axis = .horizontal | ||
horizontalStackView.backgroundColor = .black | ||
horizontalStackView.spacing = 10 | ||
horizontalStackView.distribution = .fillEqually | ||
|
||
for horIndex in 0..<4 { | ||
let button = makeButton(verIndex: verIndex, horIndex: horIndex) | ||
horizontalStackView.addArrangedSubview(button) | ||
} | ||
|
||
return horizontalStackView | ||
} | ||
|
||
// button 생성 | ||
private func makeButton(verIndex: Int, horIndex: Int) -> UIButton { | ||
let button = UIButton() | ||
let title = buttonDatas[verIndex][horIndex] | ||
let color = Int(title) == nil ? .orange : UIColor(red: 58/255, green: 58/255, blue: 58/255, alpha: 1.0) | ||
|
||
button.setTitle(title, for: .normal) | ||
button.titleLabel?.font = .boldSystemFont(ofSize: 30) | ||
button.backgroundColor = color | ||
button.layer.cornerRadius = 80 / 2 | ||
|
||
button.snp.makeConstraints() { | ||
$0.width.height.equalTo(80) | ||
} | ||
|
||
return button | ||
} | ||
|
||
// button 텍스트 변경 | ||
func setLabelText(_ text: String) { | ||
label.text = text | ||
} | ||
|
||
// 오토 레이아웃 설정 | ||
private func configureLayout() { | ||
label.snp.makeConstraints { | ||
$0.leading.trailing.equalToSuperview().inset(30) | ||
$0.top.equalToSuperview().inset(200) | ||
$0.height.equalTo(100) | ||
} | ||
|
||
verticalStackView.snp.makeConstraints { | ||
$0.top.equalTo(label.snp.bottom).offset(60) | ||
$0.centerX.equalToSuperview() | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
계산 로직을 별도의 객체로 책임분리한 점 좋습니다!
계산 로직을 잘 나타낼 수 있는 클래스 이름을 선택하면 더 좋을 것 같아요~~!