-
Notifications
You must be signed in to change notification settings - Fork 16
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
Calculator [STEP 3] Joo, Lust3r #34
Open
llimental
wants to merge
29
commits into
tasty-code:1_Lust3r
Choose a base branch
from
llimental:main
base: 1_Lust3r
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
153253c
feat: isOperator 함수 추가
llimental 42383b0
feat: addNumber() 추가
ohdair 8b2d40f
feat: isNumber 추가
llimental 43e351e
refactor: 연산자를 button의 title과 동일하게 변경
ohdair 35e810d
feat: 입력받은 숫자로 operandLabel에 반영
llimental 32cafa3
feat: 소수점을 추가해주는 addDecimalPoint 구현
ohdair 2e7e8a4
feat: operandLabel의 마지막 자리 삭제하는 clearEntry 추가
llimental a71dd15
feat: 계산기를 초기화하는 allClear 추가
ohdair 36bde4c
feat: 입력된 숫자의 부호를 바꿔주는 changeSign 추가
llimental 90611aa
feat: 연산자를 더해주는 addOperator 구현
ohdair ca7c043
refactor: 예외사항에 따른 코드 수정
llimental 026be83
feat: calculateResult 추가
llimental 98b992a
feat: 입력 내용을 보여주는 addFormulaStackView 추가
llimental d512e51
feat: allClear할 떄 scrollView의 subViews 삭제 기능 추가
ohdair e1f8c7e
feat: scrollView 하단 고정 시키는 기능 추가
ohdair 5ce428d
refactor: enteredOperand 변수 추가
llimental 87d918e
fix: calculateResult가 stack에 반영되는 문제 해결
llimental fccdbbd
feat: 천단위 구분 표시하는 formattingNumber 추가
ohdair 38e437b
feat: convertOperand 추가
llimental faf9cbf
feat: isCalculated 추가
ohdair f0ddc89
refactor: formattingNumber 반환값을 String? 에서 String 반환하도록 변경
ohdair f7bfe21
refactor: enteredOperand가 초기값인지 확인하는 isInitialOperand 추가
llimental ae1c748
refactor: 불필요한 프로퍼티 생성
ohdair 0575851
refactor: addNumber를 addOperand로 네이밍 변경
llimental 20c0e0c
Update README.md
llimental a71f398
refactor: 속성 은닉화
ohdair 3da6cdf
refactor: 자주 사용하는 "."을 상수로 정의
ohdair c5e735e
refactor: guard문의 가독성을 위해 isZero 함수로 분리
ohdair 173c537
refactor: 반복되는 구문을 메서드로 분리
ohdair File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,12 +7,173 @@ | |
import UIKit | ||
|
||
class ViewController: UIViewController { | ||
private let zero: String = "0" | ||
private let point: String = "." | ||
private var calculationFormula: String = "+" | ||
private var isDecimal: Bool = false | ||
private var isCalculated: Bool = false | ||
private var enteredOperand: String = "0" | ||
|
||
override func viewDidLoad() { | ||
super.viewDidLoad() | ||
// Do any additional setup after loading the view. | ||
} | ||
|
||
@IBOutlet weak var scrollView: UIScrollView! | ||
@IBOutlet weak var operatorLabel: UILabel! | ||
@IBOutlet weak var operandLabel: UILabel! | ||
@IBOutlet weak var formulaStackViews: UIStackView! | ||
|
||
} | ||
@IBAction func allClear(_ sender: UIButton) { | ||
operandLabel.text?.removeAll() | ||
isDecimal = false | ||
operatorLabel.text = "" | ||
calculationFormula = "+" | ||
initializeOperand() | ||
formulaStackViews.removeAllArrangedSubviews() | ||
} | ||
|
||
@IBAction func clearEntry(_ sender: UIButton) { | ||
guard isInitialOperand() == false, enteredOperand != String(Double.nan), isCalculated == false else { | ||
return | ||
} | ||
if enteredOperand.removeLast() == Character(point) { | ||
isDecimal = false | ||
} | ||
guard enteredOperand.isEmpty == false else { | ||
initializeOperand() | ||
return | ||
} | ||
operandLabel.text = formattingNumber(enteredOperand) | ||
} | ||
|
||
@IBAction func changeSign(_ sender: UIButton) { | ||
guard isInitialOperand() == false else { | ||
return | ||
} | ||
if enteredOperand.first == "-" { | ||
enteredOperand.removeFirst() | ||
} else { | ||
enteredOperand = "-" + enteredOperand | ||
} | ||
operandLabel.text = formattingNumber(enteredOperand) | ||
} | ||
|
||
@IBAction func addDecimalPoint(_ sender: UIButton) { | ||
guard isDecimal == false, isCalculated == false else { | ||
return | ||
} | ||
enteredOperand += point | ||
isDecimal = true | ||
operandLabel.text = formattingNumber(enteredOperand) + point | ||
} | ||
|
||
@IBAction func addOperand(_ sender: UIButton) { | ||
guard let number = sender.currentTitle else { | ||
return | ||
} | ||
if isCalculated { | ||
enteredOperand = zero | ||
isCalculated = false | ||
} | ||
guard isInitialOperand() == false || isZero(number) == false else { | ||
return | ||
} | ||
if isInitialOperand() { | ||
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. 조건식을 나열하지 않고 메서드를 구현해보셨네요!👍 |
||
enteredOperand = number | ||
} else { | ||
enteredOperand += number | ||
} | ||
operandLabel.text = convertOperand(enteredOperand) | ||
} | ||
|
||
@IBAction func addOperator(_ sender: UIButton) { | ||
guard let `operator` = sender.currentTitle, | ||
let enteredOperator = operatorLabel.text else { | ||
return | ||
} | ||
guard isInitialOperand() == false else { | ||
if calculationFormula == "+" { | ||
calculationFormula.removeAll() | ||
} | ||
operatorLabel.text = `operator` | ||
return | ||
} | ||
if enteredOperand.hasSuffix(point) { | ||
enteredOperand += zero | ||
} | ||
calculationFormula += enteredOperator + enteredOperand | ||
addFormulaStackView(operator: enteredOperator, operand: enteredOperand) | ||
operatorLabel.text = `operator` | ||
initializeOperand() | ||
isDecimal = false | ||
scrollView.contentOffset.y = scrollView.contentSize.height | ||
} | ||
|
||
@IBAction func calculateResult(_ sender: UIButton) { | ||
guard let enteredOperator = operatorLabel.text, calculationFormula != "+" else { | ||
return | ||
} | ||
calculationFormula += enteredOperator + enteredOperand | ||
operatorLabel.text = "" | ||
isDecimal = false | ||
isCalculated = true | ||
var formula = ExpressionParser.parse(from: calculationFormula) | ||
addFormulaStackView(operator: enteredOperator, operand: enteredOperand) | ||
enteredOperand = String(formula.result()) | ||
operandLabel.text = formattingNumber(enteredOperand) | ||
calculationFormula = "+" | ||
scrollView.contentOffset.y = scrollView.contentSize.height | ||
} | ||
|
||
private func addFormulaStackView(`operator`: String, operand: String) { | ||
let formulaStackView = UIStackView() | ||
let enteredOperatorLabel = UILabel() | ||
let enteredOperandLabel = UILabel() | ||
|
||
enteredOperandLabel.text = formattingNumber(operand) | ||
enteredOperatorLabel.text = `operator` | ||
enteredOperandLabel.textColor = .white | ||
enteredOperatorLabel.textColor = .white | ||
formulaStackView.axis = .horizontal | ||
formulaStackView.spacing = 8 | ||
formulaStackView.addArrangedSubview(enteredOperatorLabel) | ||
formulaStackView.addArrangedSubview(enteredOperandLabel) | ||
|
||
formulaStackViews.addArrangedSubview(formulaStackView) | ||
} | ||
|
||
private func formattingNumber(_ number: String) -> String { | ||
let formatter = NumberFormatter() | ||
formatter.maximumFractionDigits = 20 | ||
formatter.numberStyle = .decimal | ||
return formatter.string(for: Double(number)) ?? number | ||
} | ||
|
||
private func convertOperand(_ operand: String) -> String { | ||
if let indexOfPoint = operand.firstIndex(of: Character(point)) { | ||
let integerOfOperand = String(operand[operand.startIndex..<indexOfPoint]) | ||
var decimalOfOperand: String | ||
if operand.distance(from: indexOfPoint, to: operand.endIndex) > 20 { | ||
let twentyIndex = operand.index(indexOfPoint, offsetBy: 20) | ||
decimalOfOperand = String(operand[indexOfPoint...twentyIndex]) | ||
} else { | ||
decimalOfOperand = String(operand[indexOfPoint..<operand.endIndex]) | ||
} | ||
return formattingNumber(integerOfOperand) + decimalOfOperand | ||
} | ||
return formattingNumber(operand) | ||
} | ||
|
||
private func isInitialOperand() -> Bool { | ||
return enteredOperand == zero | ||
} | ||
|
||
private func isZero(_ value: String) -> Bool { | ||
return value == zero || value == "00" | ||
} | ||
|
||
private func initializeOperand() { | ||
enteredOperand = zero | ||
operandLabel.text = zero | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// | ||
// UIStackView+Extension.swift | ||
// Calculator | ||
// | ||
// Created by 박재우 on 2023/02/02. | ||
// | ||
|
||
import UIKit | ||
|
||
extension UIStackView { | ||
func removeAllArrangedSubviews() { | ||
arrangedSubviews.forEach { | ||
self.removeArrangedSubview($0) | ||
$0.removeFromSuperview() | ||
} | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
여러 메서드에서 해당 구문이 반복되고 있습니다. 이를 메서드로 분리해보면 하는 것은 어떨까요?
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.
아래와 같이 메서드로 분리해서 사용했습니다