Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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 "오류"

Choose a reason for hiding this comment

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

Error 를 정의해서 처리하면 어떨까요?

}
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,
let decimal = Int(decimalString),
var decimalFormat = numberFormatter.string(from: NSNumber(value: decimal))
else { return "오류"}
if 1 < decimalFractionComponents.count, let fractionString = decimalFractionComponents.last {

Choose a reason for hiding this comment

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

1 < decimalFractionComponents.count
decimalFractionComponents.count > 1
위 두 코드를 우리는 어떻게 읽을까요?

  • 1 보다 값이 큰 경우
  • 값이 1보다 큰 경우

가독성을 고려해볼까요?

Choose a reason for hiding this comment

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

적절한 줄바꿈은 가독성을 증가시킬 수 있습니다

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
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 = "오류"
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 {
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
.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