在具有錯誤的視圖文件中的行是:
顯示器= brain.evaluateWithErrorReport(使用:dictionaryForVaribles)displays = brain.evaluateWithErrorReport(using:dictionaryForVaribles)給出一個錯誤,除非一個as!被添加。爲什麼?
我接收是錯誤:
/Users/Tom/Developer/Stsnford-IOS 10 Course/Calculator_IOS10/Calculator_IOS10/ViewController.swift:166:26: Cannot assign value of type '(result: Double?, isPending: Bool, description: String, errorDescription: String?)' (aka '(result: Optional<Double>, isPending: Bool, description: String, errorDescription: Optional<String>)') to type '(result: Double, isPending: Bool, sequence: String, errorMessage: String?)' (aka '(result: Double, isPending: Bool, sequence: String, errorMessage: Optional<String>)')
編譯器說,修復是要加上: as! (result:double,isPending:Bool,sequence:String,errorMessage:String?)
所以現在看起來像這樣: displays = brain.evaluateWithErrorReport(using:dictionaryForVaribles)as! (result:double,isPending:Bool,sequence:String,errorMessage:String?)
爲什麼沒有as! ?
該程序有兩個文件,它是iTunes上CS193P的作業2。
查看文件:
//
// ViewController.swift
// Calculator_IOS10
//
// Created by Theophilos Aravanis on 4/12/17.
// Copyright © 2017 Theophilos Aravanis. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var calculatorDisplay: UILabel!
@IBOutlet weak var discriptionDisplay: UILabel!
@IBOutlet weak var varibleDisplay: UILabel!
var displays: (result: Double, isPending:Bool, sequence:String, errorMessage:String?) {
get {
return (Double(calculatorDisplay.text!)!, false, discriptionDisplay.text!, nil)
}
set {
if newValue.errorMessage != " " {
calculatorDisplay.text = newValue.errorMessage
} else {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 6
calculatorDisplay.text = formatter.string(from:(NSNumber(value:newValue.result)))
}
if newValue.sequence.isEmpty {
discriptionDisplay.text = " "
} else {
discriptionDisplay.text = newValue.sequence + (brain.resultIsPending ? " …" : " =")
}
if let varibaleValue = dictionaryForVaribles["M"] {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 6
varibleDisplay.text = formatter.string(from:(NSNumber(value:varibaleValue)))
} else {
varibleDisplay.text = " "
}
} // end of set
}
var userInMiddleOfTyping = false
var currentDisplay = " "
var dictionaryForVaribles = [String:Double]()
@IBAction func digitTouched(_ sender: UIButton) {
let digit = sender.currentTitle!
if userInMiddleOfTyping {
let currentlyDisplayedText = calculatorDisplay.text!
switch digit {
case ".":
if currentlyDisplayedText.contains("."){
calculatorDisplay.text = currentlyDisplayedText
}
else {
calculatorDisplay.text = currentlyDisplayedText + digit
}
case "BS":
currentDisplay = calculatorDisplay.text!
if currentDisplay.isEmpty == false {
currentDisplay.remove(at: currentDisplay.index(before: currentDisplay.endIndex))
if currentDisplay.isEmpty {
calculatorDisplay.text = "0"
userInMiddleOfTyping = false
} else {
calculatorDisplay.text = currentDisplay
userInMiddleOfTyping = true
}
}
default:
calculatorDisplay.text = currentlyDisplayedText + digit
}
}
else {
switch digit {
case "bs":
break
default:
calculatorDisplay.text = digit
userInMiddleOfTyping = true
}
}
}
/* var displayValue:Double{
get {
return Double(calculatorDisplay.text!)!
}
set {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 6
calculatorDisplay.text = formatter.string(from:(NSNumber(value:newValue)))
}
}
var displayDescription:String{
get {
return discriptionDisplay.text!
}
set {
discriptionDisplay.text = newValue + (brain.resultIsPending ? " …" : " =")
}
} */
private var brain = CalculatorBrain()
func showDescriptionDisplay() {
discriptionDisplay.isHidden = false
}
func hideDescriptionDisplay() {
discriptionDisplay.isHidden = true
}
func showVaribleDisplay() {
varibleDisplay.isHidden = false
}
func hideVaribleDisplay() {
varibleDisplay.isHidden = true
}
@IBAction func allClear(_ sender: UIButton) {
hideDescriptionDisplay()
discriptionDisplay.text = " "
calculatorDisplay.text = "0"
userInMiddleOfTyping = false
brain.clearAccumulator()
}
@IBAction func setVarible(_ sender: UIButton) {
let symbol = sender.currentTitle!
brain.setOperand(variable:symbol)
}
@IBAction func evaluateVarible(_ sender: UIButton) {
}
@IBAction func performOperation(_ sender: UIButton) {
showDescriptionDisplay()
if userInMiddleOfTyping {
brain.setOperand(displays.result)
userInMiddleOfTyping = false
}
if let mathimaticalSymbol = sender.currentTitle {
brain.performOperation(mathimaticalSymbol)
}
displays = brain.evaluateWithErrorReport(using: dictionaryForVaribles) as! (result: Double, isPending: Bool, sequence: String, errorMessage: String?)
/* if let result = brain.result {
displays.result = result
}
// if let descriptionLine = brain.line {
// displays.sequence = descriptionLine
// } */
}
}
模型文件:
//
// CalculatorBrain_IOS10.swift
// Calculator_IOS10
//
// Created by Theophilos Aravanis on 4/14/17.
// Copyright © 2017 Theophilos Aravanis. All rights reserved.
//
import Foundation
func factorial(_ op1: Double) -> Double {
if (op1 <= 1.0) {
return 1.0
}
return op1 * factorial(op1 - 1.0)
}
struct CalculatorBrain {
var result:Double? {
get {
return accumulator?.0
}
}
// @available(*, deprecated, message: "Use evaluate instead")
var resultIsPending = false
private var accumulator:(digit:Double, description:String?, errorMessage:String?)?
private enum MemoryVarible {
case operand(Double)
case operation(String)
case variable(String)
}
private var memorySequence = [MemoryVarible]()
private enum Operation {
case constant(Double)
case nullOperation(() -> Double, String)
case unaryOperation((Double) -> Double, (String) -> String, (Double) -> String?)
case binaryOperation((Double,Double) -> Double, (String, String) -> String, (Double,Double) -> String?)
case equals
}
private var operations:Dictionary<String,Operation> =
[
"rand": .nullOperation({Double(arc4random())/Double(UInt32.max)}, "rand()"),
"π" : .constant(M_PI),
"e" : .constant(M_E),
"√" : .unaryOperation(sqrt,{"√(" + $0 + ")"},{$0 < 0 ? "Sqrt of negative number" : nil}),
"cos" :.unaryOperation(cos,{"cos(" + $0 + ")"},{ _ in nil}),
"∓" : .unaryOperation({-$0},{"-(" + $0 + ")"},{ _ in nil}),
"x²" :.unaryOperation({ pow($0, 2) }, { "(" + $0 + ")²" },{ _ in nil}),
"x³" :.unaryOperation({ pow($0, 3) }, { "(" + $0 + ")³" },{ _ in nil}),
"x⁻¹" :.unaryOperation({ 1/$0 }, { "(" + $0 + ")⁻¹" },{ _ in nil}),
"sin" :.unaryOperation(sin, { "sin(" + $0 + ")" },{ _ in nil}),
"tan" :.unaryOperation(tan, { "tan(" + $0 + ")" },{ _ in nil}),
"sinh" :.unaryOperation(sinh, { "sinh(" + $0 + ")" },{ _ in nil}),
"cosh" :.unaryOperation(cosh, { "cosh(" + $0 + ")" },{ _ in nil}),
"tanh" :.unaryOperation(tanh, { "tanh(" + $0 + ")" },{ _ in nil}),
"ln" : .unaryOperation(log, { "ln(" + $0 + ")" },{ _ in nil}),
"log" : .unaryOperation(log10, { "log(" + $0 + ")" },{ _ in nil}),
"eˣ" :.unaryOperation(exp, { "e^(" + $0 + ")" },{ _ in nil}),
"10ˣ" :.unaryOperation({ pow(10, $0) }, { "10^(" + $0 + ")" },{ _ in nil}),
"x!" :.unaryOperation(factorial, { "(" + $0 + ")!" },{ _ in nil}),
"xʸ" :.binaryOperation(pow, { $0 + "^" + $1 },{ _,_ in nil}),
"+" : .binaryOperation(+,{$0 + "+" + $1},{ _,_ in nil}),
"−" : .binaryOperation(-,{$0 + "-" + $1},{ _,_ in nil}),
"÷" : .binaryOperation(/,{$0 + "÷" + $1}, {_,_ in nil }),
"×" : .binaryOperation(*,{$0 + "*" + $1},{ _,_ in nil}),
"=" : .equals
]
mutating func clearAccumulator() {
accumulator?.errorMessage = nil
accumulator?.description = " "
accumulator?.digit = 0
}
mutating func evaluate(using variables: Dictionary<String,Double>? = nil) -> (result: Double?, isPending: Bool, description: String) {
let (result, isPending, description, _) = evaluateWithErrorReport(using: variables)
return (result, isPending, description)
}
mutating func performOperation(_ symbol: String) {
memorySequence.append(MemoryVarible.operation(symbol))
}
mutating func setOperand(_ operand: Double) {
memorySequence.append(MemoryVarible.operand(operand))
}
mutating func setOperand(variable named: String) {
memorySequence.append(MemoryVarible.variable(named))
}
mutating func evaluateWithErrorReport(using variables: Dictionary<String,Double>? = nil) -> (result: Double?, isPending: Bool, description: String, errorDescription: String?) {
var pendingBinaryOperation:PendingBinaryOperation?
var calculationDescription:String? {
get {
if pendingBinaryOperation == nil {
return accumulator?.description
} else {
return pendingBinaryOperation!.calculationDescription(pendingBinaryOperation!.descriptionOperand, accumulator?.description ?? " ")
}
}
}
var line:String? {
get {
return calculationDescription
}
}
func performOperation(_ symbol:String){
if let currentOperation = operations[symbol] {
switch currentOperation {
case .nullOperation(let function, let nullDiscription):
accumulator = (function(), nullDiscription, nil)
case .constant(let value):
accumulator = (value,symbol, nil)
case .unaryOperation(let function, let unaryDescription, let unaryMemory):
if accumulator != nil {
accumulator = (function(accumulator!.digit), unaryDescription(accumulator!.description!),
unaryMemory(accumulator!.digit))
}
case .binaryOperation(let binaryFunction,
let binaryDescription,
let binaryError):
if accumulator != nil {
doAPendingBinaryOperation()
resultIsPending = true
pendingBinaryOperation = PendingBinaryOperation(
calculationError:binaryError,
mathFunction: binaryFunction,
calculationDescription:binaryDescription,
firstOperand: accumulator!.digit,
descriptionOperand:(accumulator?.description)!)
accumulator = nil
}
case .equals:
doAPendingBinaryOperation()
resultIsPending = false
}
}
}
func doAPendingBinaryOperation() {
if pendingBinaryOperation != nil && accumulator != nil {
accumulator!.description = calculationDescription!
accumulator!.digit = pendingBinaryOperation!.perform(with: accumulator!.digit)
accumulator!.errorMessage = "Future enhancement"
pendingBinaryOperation = nil
}
}
struct PendingBinaryOperation {
let calculationError: (Double, Double) -> String?
let mathFunction: (Double, Double) -> Double
let calculationDescription: (String, String) -> String
let firstOperand: (Double)
let descriptionOperand:(String)
func perform(with secondOperand:(Double)) -> Double {
return (mathFunction(firstOperand, secondOperand))
}
func performDecription(with secondOperan:(String)) -> String {
return (calculationDescription(descriptionOperand, secondOperan))
}
}
func setOperand(_ operand:Double) {
accumulator = (operand, String(Int(operand)), nil)
}
func setOperand(variable named: String) {
accumulator = (variables?[named] ?? 0, named, nil)
}
for item in memorySequence {
switch item {
case .operand(let operand):
setOperand(operand)
case .operation(let operation):
performOperation(operation)
case .variable(let variable):
setOperand(variable:variable)
}
}
if pendingBinaryOperation != nil {
return (accumulator!.digit, true, pendingBinaryOperation!.calculationDescription(pendingBinaryOperation!.descriptionOperand, accumulator!.description ?? ""), accumulator?.errorMessage)
} else {
return (accumulator!.digit, false, accumulator!.description ?? "", accumulator?.errorMessage)
}
} // end of evaluate with errors
}
我試過了,仍然得到了同樣的錯誤。看來errorMessage是問題發生的地方。 –
我通過將兩個display.result和accumulator.digit更改爲可選項來修復它。修復了導致代碼編譯沒有錯誤的所有語法錯誤之後。 –