如图:
涉及到以下知识:
do {
} catch let error {
}try
throws
guard
extension
contains
UIStackView
布局 - UIStackView
throws
配合 do {
使用
} catch let error {
}
如:
do {
throw CalculatorError.nilInput
} catch let error{
print("\(error.localizedDescription)")
}
其中:
public enum CalculatorError: Error {
case invalidCharater
case multipleCharacters
case nilInput
}
可以配合使用:
do {
guard let input = input else {
throw CalculatorError.nilInput
}
} catch let error{
print("\(error.localizedDescription)")
}
再深入一点
声明:
func iInputChara(_ input: String?) throws {
guard let input = input else {
throw CalculatorError.nilInput
}
}
使用
override func viewDidLoad() {
super.viewDidLoad()
do {
try iInputChara("d")
} catch let error{
print("\(error.localizedDescription)")
}
}
下面开始计算器代码:
open class Calculator {
}
open 该权限是最大的权限,允许访问文件,同时允许继承、重写
public init() {
self.display = String()
self.operatorValue = nil
}
public 允许访问但不允许继承、重写
fileprivate let period = "."
fileprivate var display: String
fileprivate var leftOperand: Double?
fileprivate var operatorValue: String?
fileprivate var isLastCharacterOperator = false
fileprivate
设为私有属性
fileprivate 允许文件内访问
private 只允许当前对象的代码块内部访问
public var displayValue: String {
get {
return !(display.isEmpty) ? display : "0"
}
}
重写get方法,使得每次获取displayValue时都取决于!(display.isEmpty),这个很高明
public func input(_ input: String?) throws {
}
_ input: String?
说明传参可为空
guard let input = input else {
throw CalculatorError.nilInput
}
判断参数为空时抛出错误
一个String的extension
extension String {
/// Determines whether the string is the Delete charater.
var isDelete: Bool {
return (self == "D")
}
/// Determines whether the string is a period.
var isPeriod: Bool {
return (self == ".")
}
/// Determines whether the string is the Clear charater.
var isClear: Bool {
return (self == "C")
}
/// Determines whether the string is a period or a number between 0 and 9.
var isValidDigit: Bool {
let digits = "0123456789."
return digits.contains(self)
}
/// Determines whether the string is an operator such as +, -, *, or /.
var isOperator: Bool {
let operators = "+-*/"
return operators.contains(self)
}
/// Determines whether the string is an equal sign.
var isEqualSign: Bool {
return (self == "=")
}
/// Determines whether a string is a valid character such as a digit, a.
var isValidCharacter: Bool {
return ( isValidDigit || isOperator || isDelete || isClear || isPeriod || isEqualSign)
}
}
上文已经声明了一个枚举,下面扩展LocalizedError协议
public enum CalculatorError: Error {
case invalidCharater
case multipleCharacters
case nilInput
}
extension CalculatorError: LocalizedError {
public var errorDescription: String? {
switch self {
case .invalidCharater: return NSLocalizedString("Invalid character exception.", comment: "The input is not a number between 0-9, an operator (+, -, *, /), D, C, =, or a period.")
case .multipleCharacters: return NSLocalizedString("Multiple characters exception.", comment: "The input contains more than one character.")
case .nilInput: return NSLocalizedString("Nil exception.", comment: "The input is nil.")
}
}
}
然后就是逻辑处理了
// If the inputted character is a number (between 0 and 9) or a period, update the display.
if input.isValidDigit {
if isLastCharacterOperator {
display = input
isLastCharacterOperator = false
}
else if !input.isPeriod || !(display.contains(period)) {
// Add it to the current display.
display += input
}
}
/*
If the inputted character is an operator, save it in operatorValue and the current displayed value in leftOperand.
If the inputted character is an equal sign, call the operation function to perform a calculation
using leftOperand, the current displayed value, and operatorValue, then save the result in the display variable.
*/
else if input.isOperator || input.isEqualSign {
if (operatorValue == nil) && !(input.isEqualSign) {
leftOperand = Double(displayValue)
operatorValue = input
}
else {
if let sign = operatorValue, let operand = leftOperand, let rightOperand = Double(displayValue) {
if let result = operation(left: operand, right: rightOperand, sign: sign) {
// Update the display with the operation's result.
display = "\(String(format: "%g", result))"
}
}
operatorValue = (input.isEqualSign) ? nil : input
}
isLastCharacterOperator = true
}
// if the inputted character is "C" and there is something displayed, clear it. Clear the saved operator, otherwise.
else if input.isClear {
if !(display.characters.isEmpty) {
display.removeAll()
}
else {
operatorValue = nil
}
}
// If the inputted character is "D" and there is something displayed, remove its last character.
else if input.isDelete {
if !display.isEmpty {
display = String(display.characters.dropLast())
}
isLastCharacterOperator = false
}
可以看出,一个简单地计算器Demo写的如此精美,大家可以细细品味