Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions week4/Calculator/Calculator.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
A67D5A3228AB573F00624B25 /* CalculatorManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A67D5A3128AB573F00624B25 /* CalculatorManager.swift */; };
A67D5A3428AB68B200624B25 /* PadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A67D5A3328AB68B200624B25 /* PadView.swift */; };
A67D5A3A28ADC86000624B25 /* ScreenView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A67D5A3928ADC86000624B25 /* ScreenView.swift */; };
A67D5A3C28ADCA6C00624B25 /* EachButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = A67D5A3B28ADCA6C00624B25 /* EachButton.swift */; };
A67D5A3C28ADCA6C00624B25 /* PadButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = A67D5A3B28ADCA6C00624B25 /* PadButton.swift */; };
A67D5A3E28ADD28D00624B25 /* ButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = A67D5A3D28ADD28D00624B25 /* ButtonStyle.swift */; };
A67D5A5628B7024800624B25 /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A67D5A5528B7024800624B25 /* String+Extension.swift */; };
A67D5A5928B74B3200624B25 /* Numeric+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A67D5A5828B74B3200624B25 /* Numeric+Extension.swift */; };
Expand All @@ -32,7 +32,7 @@
A67D5A3128AB573F00624B25 /* CalculatorManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalculatorManager.swift; sourceTree = "<group>"; };
A67D5A3328AB68B200624B25 /* PadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PadView.swift; sourceTree = "<group>"; };
A67D5A3928ADC86000624B25 /* ScreenView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenView.swift; sourceTree = "<group>"; };
A67D5A3B28ADCA6C00624B25 /* EachButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EachButton.swift; sourceTree = "<group>"; };
A67D5A3B28ADCA6C00624B25 /* PadButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PadButton.swift; sourceTree = "<group>"; };
A67D5A3D28ADD28D00624B25 /* ButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonStyle.swift; sourceTree = "<group>"; };
A67D5A5528B7024800624B25 /* String+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = "<group>"; };
A67D5A5828B74B3200624B25 /* Numeric+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Numeric+Extension.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -103,7 +103,7 @@
A67D5A2028AB566600624B25 /* CalculatorView.swift */,
A67D5A3328AB68B200624B25 /* PadView.swift */,
A67D5A3928ADC86000624B25 /* ScreenView.swift */,
A67D5A3B28ADCA6C00624B25 /* EachButton.swift */,
A67D5A3B28ADCA6C00624B25 /* PadButton.swift */,
);
path = View;
sourceTree = "<group>";
Expand Down Expand Up @@ -206,7 +206,7 @@
files = (
A67D5A5628B7024800624B25 /* String+Extension.swift in Sources */,
A67D5A5928B74B3200624B25 /* Numeric+Extension.swift in Sources */,
A67D5A3C28ADCA6C00624B25 /* EachButton.swift in Sources */,
A67D5A3C28ADCA6C00624B25 /* PadButton.swift in Sources */,
A67D5A3E28ADD28D00624B25 /* ButtonStyle.swift in Sources */,
A67D5A3428AB68B200624B25 /* PadView.swift in Sources */,
A67D5A2128AB566600624B25 /* CalculatorView.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import Foundation

extension Numeric {
var exponentialNotation: String {
return Formatter.exponentialNotation.string(for: self) ?? ""
guard let exponentialNotationString = Formatter.exponentialNotation.string(for: self) else {
return "오류"
}
return exponentialNotationString
}
}
22 changes: 9 additions & 13 deletions week4/Calculator/Calculator/Extensions/String+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,17 @@
import Foundation

extension String {
var insertComma: String {
var decimalFormat: String {
let numberFormatter = NumberFormatter();
numberFormatter.numberStyle = .decimal
if self.contains(".") {
let numberArray = self.components(separatedBy: ".")
let numberString = numberArray.first ?? "0"
guard let doubleValue = Double(numberString) else {
return self
}
return (numberFormatter.string(from: NSNumber(value: doubleValue)) ?? numberString) + ".\(numberArray[numberArray.index(numberArray.startIndex, offsetBy: 1)])"
} else {
guard let doubleValue = Double(self) else {
return self
}
return numberFormatter.string(from: NSNumber(value: doubleValue)) ?? self
let decimalFractionComponents = components(separatedBy: ".")
guard let decimalString = decimalFractionComponents.first,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코드를 그대로 사용한 것이지만, 문법은 통일해 주세요.

guard let safeValue = unsafeValue else {
    return
}

vs

guard let safeValue = unsafeValue
else { return }

let decimal = Int(decimalString),
var decimalFormat = numberFormatter.string(from: NSNumber(value: decimal))
else { return "오류"}
if 1 < decimalFractionComponents.count, let fractionString = decimalFractionComponents.last {
decimalFormat += ".\(fractionString)"
}
return decimalFormat
}
}
177 changes: 121 additions & 56 deletions week4/Calculator/Calculator/Model/Calculator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,14 @@ import Foundation

struct Calculator {

// MARK: Alias(es)

typealias BinaryOperator = CalculatorManager.BinaryOperator
typealias Digit = CalculatorManager.Digit

// MARK: Propery(ies)

private(set) var displayValue = "0"
private(set) var isAllClear = true
private var calculationResult: Decimal? = 0
private var newValue: Decimal? = nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네이밍 개선하면 가독성을 더 올릴 수 있을 거 같네요.

private var operation: BinaryOperator? = .add
private var `operator`: BinaryOperator? = .add
private var isPreOperatorEqual = false
private var isCalculationResultIsNil: Bool {
calculationResult == nil
}
Expand All @@ -33,44 +29,47 @@ struct Calculator {
self.newValue = Decimal(string: displayValue)
isAllClear = false
} else {
if String(describing: self.newValue ?? 0).count >= 9 {
let maxLengthOfInputDigit = displayValue.contains(".") ? 10 : 9
if displayValue.count >= maxLengthOfInputDigit {
return
}
displayValue = displayValue.appending(String(describing: newValue.rawValue))
self.newValue = Decimal(string: displayValue)
}
}

mutating func setOperation(_ newOperation: BinaryOperator) {
guard let operation = operation, let newValue = newValue else {
self.operation = newOperation
return
mutating func setOperator(_ newOperator: BinaryOperator) {
if isPreOperatorEqual {
`operator` = nil
newValue = nil
isPreOperatorEqual = false
}
calculationResult = calculate(operation, newValue)
guard let calculationResult = calculationResult else {
displayValue = "오류"
return
}
displayValue = String(describing: calculationResult)
proveAndCalculate(newOperator: newOperator)
self.newValue = nil
self.operation = newOperation
self.`operator` = newOperator
}

mutating func equal() {
guard let operation = operation, let newValue = newValue else {
proveAndCalculate(newOperator: nil)
}

private mutating func proveAndCalculate(newOperator: BinaryOperator?) {
let isEqual = newOperator == nil
guard let `operator` = `operator`, let newValue = newValue else {
return
}
calculationResult = calculate(operation, newValue)
if isEqual {
isPreOperatorEqual = true
}
calculationResult = calculate(`operator`, newValue)
guard let calculationResult = calculationResult else {
displayValue = "오류"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"오류"라는 string 값이 많은데,
이거 상수로 두고 모든 부분에 적용시키면 나중에 하나만 변경시켜도 되니까 좀더 관리하기 쉬울것같아요 ㅎㅎ
let errorMessage = "오류"

displayValue = errorMessage 이렇게?

self.newValue = nil
return
}
displayValue = String(describing: calculationResult)
self.newValue = nil
self.operation = nil
}

mutating func dot() {
if displayValue.contains(".") || isCalculationResultIsNil {
return
Expand All @@ -81,36 +80,32 @@ struct Calculator {
}

mutating func percent() {
guard let calculationResult = calculationResult else {
return
}
if let newValue = newValue {
displayValue = String(describing: newValue * 0.01)
self.newValue = Decimal(string: displayValue)
} else {
displayValue = String(describing: calculationResult * 0.01)
self.calculationResult = Decimal(string: displayValue)
}
percentOrToggleSignOfDisplayNumber(isToggle: false)
}

mutating func toggleSignOfDisplayNumber() {
percentOrToggleSignOfDisplayNumber(isToggle: true)
}

mutating func toggle() {
private mutating func percentOrToggleSignOfDisplayNumber(isToggle: Bool) {
guard let calculationResult = calculationResult else {
return
}
if let newValue = newValue {
displayValue = String(describing: -newValue)
let operand = isToggle ? -1 : 0.01
if let newValue = newValue, !isPreOperatorEqual {
displayValue = String(describing: newValue * Decimal(operand))
self.newValue = Decimal(string: displayValue)
} else {
displayValue = String(describing: -calculationResult)
displayValue = String(describing: calculationResult * Decimal(operand))
self.calculationResult = Decimal(string: displayValue)
}
}

mutating func allClear() {
displayValue = "0"
newValue = nil
clear()
isPreOperatorEqual = false
calculationResult = 0
operation = .add
`operator` = .add
}

mutating func clear() {
Expand All @@ -120,22 +115,21 @@ struct Calculator {
}

mutating func undoWhenDragged() {
if newValue == nil {
if displayValue.count > 1 {
displayValue.removeLast()
calculationResult = Decimal(string: displayValue)
} else if displayValue.count == 1 {
displayValue = "0"
calculationResult = Decimal(string: displayValue)
}
let isNewValueNil = newValue == nil
if displayValue.count == 1 {
displayValue = "0"
assignValueWhenUndo(isNewValueNil)
} else {
if displayValue.count > 1 {
displayValue.removeLast()
newValue = Decimal(string: displayValue)
} else if displayValue.count == 1 {
displayValue = "0"
newValue = Decimal(string: displayValue)
}
displayValue.removeLast()
assignValueWhenUndo(isNewValueNil)
}
}

private mutating func assignValueWhenUndo(_ newValueIsNil: Bool) {
if newValueIsNil {
calculationResult = Decimal(string: displayValue)
} else {
newValue = Decimal(string: displayValue)
}
}

Expand All @@ -150,11 +144,82 @@ struct Calculator {
return calculationResult - newValue
case .divide:
if newValue == 0 {
return nil
return nil
}
return calculationResult / newValue
case .multiply:
return calculationResult * newValue
}
}
}

extension Calculator {
enum Button: Hashable {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Button ?

case digit(_ digit: Digit)
case binaryOperator(_ binaryOperator: BinaryOperator)
case equal
case dot
case percent
case toggle
case allClear
case clear

var appearance: String {
switch self {
case .digit(let digit):
return digit.appearance
case .binaryOperator(let binaryOperator):
return binaryOperator.appearance
case .equal:
return "="
case .dot:
return "."
case .percent:
return "%"
case .toggle:
return "+/-"
case .allClear:
return "AC"
case .clear:
return "C"
}
}
}

enum BinaryOperator {
case add
case substarct
case divide
case multiply

var appearance: String {
switch self {
case .add:
return "+"
case .substarct:
return "-"
case .divide:
return "/"
case .multiply:
return "*"
}
}
}

enum Digit: Int {
case zero
case one
case two
case three
case four
case five
case six
case seven
case eight
case nine

var appearance: String {
return String(describing: self.rawValue)
}
}
}
44 changes: 16 additions & 28 deletions week4/Calculator/Calculator/Style/ButtonStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,24 @@
import SwiftUI

struct CalculateButtonStyle: ButtonStyle {
let buttonColor: (Color, Color)
let buttonColor: (background: Color, foreground: Color)
let isZero: Bool

func makeBody(configuration: Self.Configuration) -> some View {
if isZero {
configuration.label
.frame(maxWidth:UIScreen.main.bounds.size.width / 2, maxHeight: UIScreen.main.bounds.size.height / 12, alignment: .leading)
.font(.title)
.padding()
.background(buttonColor.0)
.foregroundColor(buttonColor.1)
.overlay {
if configuration.isPressed {
Color(white: 1.0, opacity: 0.3)
}
}
.clipShape(Capsule())
} else {
configuration.label
.frame(maxWidth:UIScreen.main.bounds.size.width / 6.5, maxHeight: UIScreen.main.bounds.size.height / 12, alignment: .center)
.font(.title)
.padding()
.background(buttonColor.0)
.foregroundColor(buttonColor.1)
.overlay {
if configuration.isPressed {
Color(white: 1.0, opacity: 0.3)
}
configuration.label
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

상수는 따로 모아서 처리해주면 좋겠네요

.frame(
maxWidth:UIScreen.main.bounds.size.width / (isZero ? 2.0 : 6.5),
maxHeight: UIScreen.main.bounds.size.height / 12,
alignment: isZero ? .leading : .center)
.font(.title)
.padding()
.background(buttonColor.background)
.foregroundColor(buttonColor.foreground)
.overlay {
if configuration.isPressed {
Color(white: 1.0, opacity: 0.3)
}
.clipShape(Circle())
}
}
.clipShape(Capsule())
}
}
Loading