Mortgage Calculator Swift - swift

I am a beginner with Xcode and Swift. Below is my formula for the mortgage calculator. It is working correct in Playground but when I transfer it to the ViewController tab that is when Xcode is giving me a bunch of errors. Can someone please help?
let r: Double = interestRate / 1200
let n: Double = years * 12
let p: Double = pow(1 + r, n)
let monthPay = loan * r * p / (p - 1)
print(monthPay)
So in my View Controller
valueA is Loan Amount
valueB is Number of Payments
valueC is Interest Rate
underneath that you will have a calculate button that will print the results underneath in a label currently named results. It may be that when i rename everything to the values is when the issues occur.
ViewController Code
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var valueA: UITextField!
#IBOutlet weak var valueB: UITextField!
#IBOutlet weak var valueC: UITextField!
#IBOutlet weak var results: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func button(_ sender: Any) {
let a = Int(valueA.text!)
let b = Int(valueB.text!)
let c = Int(valueC.text!)
let answer = a! * c! * pow(1 + c!, b!) / (pow(1 + c!, b!))
results.text = "$\(answer)"
}
}

Your issue is that you are converting your textfield values to integers and trying to multiply them by the result of pow's method which returns a Double. Note that if the user enters an invalid value your app will crash if you force unwrap the result. Yo can use nil coalescing operator ?? to provide a default value .zero in case of failure. Try like this:
class ViewController: UIViewController {
#IBOutlet weak var valueA: UITextField! // loan amount
#IBOutlet weak var valueB: UITextField! // Number of Payments
#IBOutlet weak var valueC: UITextField! // Interest Rate
#IBOutlet weak var results: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func button(_ sender: Any) {
let loanAmount = Double(valueA.text!) ?? .zero
let numberOfPayments = Double(valueB.text!) ?? .zero
let interestRate = Double(valueC.text!) ?? .zero
let rate = interestRate / 100 / 12
let answer = loanAmount * rate / (1 - pow(1 + rate, -numberOfPayments))
results.text = Formatter.currency.string(for: answer)
}
}
extension Formatter {
static let currency: NumberFormatter = {
let formatter = NumberFormatter()
formatter.locale = .init(identifier: "en_US_POSIX")
formatter.numberStyle = .currency
return formatter
}()
}

Related

using String with UIStepper - Swift

i have a label and a UIStepper, i need to increase the number of that label without lossing the letters ( Kd ) . my label will be like this "5.000 Kd" and when i increase the number i don't want to loss the ( Kd ) label.
this is my code
import UIKit
import GMStepper
class ViewController: UIViewController {
#IBOutlet var stepper: GMStepper!
#IBOutlet var price: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func stepper(_ sender: Any) {
let label = "5.000 Kd" as NSString
price.text! = String(label.doubleValue * stepper.value)
}
}
If you are hard-coding the string contents of the label, just maintain a numeric value and rebuild the label contents each time that value changes:
class ViewController: UIViewController {
#IBOutlet var stepper: GMStepper!
#IBOutlet var priceLabel: UILabel!
var price: Double = 5.0
#IBAction func stepper(_ sender: Any) {
let newValue = price * stepper.value
//Format the price with 3 decimal places
let priceString = String(format: "%.3f", newValue)
Construct a string with the formatted price and " Kd" and put it in the label
priceLabel.text = "\(priceString) Kd")
}
}
Consider using NumberFormatter to format currency:
let cf = NumberFormatter()
cf.currencyCode = "KWD"
cf.numberStyle = .currency
cf.string(from: 5000)
That respects the user's Locale.

How do I store a calculated result in UserDefaults to display in a "results" View controller [duplicate]

This question already has answers here:
How can I use UserDefaults in Swift?
(14 answers)
Closed 4 years ago.
First time poster so sorry for the incorrect format/length of the question.
I am building an app in Xcode that allows users to input various inputs among numerous view controllers and then have output in a single view controller with results displayed through labels.
The raw inputted textfield data is stored into UserDefaults and can display them later in the resulting VC with no problem. Im having trouble with calculated outputs (in this example "papiresult") however.
Can anyone provide guidance how to print out the calculated result several view controllers later using UserDefaults?
This is the rough layout
Here is the code I have in the first ViewController:
import UIKit
let userDefaults = UserDefaults()
var papiresult = Double()
class ViewController1: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField1: UITextField!
#IBOutlet weak var textField2: UITextField!
#IBOutlet weak var textField3: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
textField1.delegate = self
textField2.delegate = self
textField3.delegate = self
}
//Declaring data input into UserDefaults//
#IBAction func sendDataToVC2(_ sender: Any) {
let systPA = Double(textField1.text!)
let diastPA = Double(textField2.text!)
let cvPressure = Double(textField3.text!)
papiresult = ((systPA!-diastPA!)/cvPressure!)
userDefaults.set(textField1.text, forKey: "PASP")
userDefaults.set(textField2.text, forKey: "PADP")
userDefaults.set(textField3.text, forKey: "CVP")
userDefaults.set(papiresult, forKey: "PAPI")
}
}
Here is the code in the last (result) view controller:
import UIKit
class ViewController3: UIViewController {
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label3: UILabel!
#IBOutlet weak var label4: UILabel!
#IBOutlet weak var label5: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
//Recalling data from UserDefaults//
override func viewWillAppear(_ animated: Bool) {
if let data1 = userDefaults.object(forKey: "PASP") {
if let message1 = data1 as? String {
self.label1.text = message1}
}
if let data2 = userDefaults.object(forKey: "PADP") {
if let message2 = data2 as? String {
self.label2.text = message2}
}
if let data3 = userDefaults.object(forKey: "CVP") {
if let message3 = data3 as? String {
self.label3.text = message3}
}
if let data4 = userDefaults.object(forKey: "Age") {
if let message4 = data4 as? String {
self.label4.text = message4}
}
if let data5 = userDefaults.object(forKey: "PAPI") {
if let message5 = data5 as? Double {
self.label5.text = "\(message5)"}
}
}
Basically, you should use UserDefaults.standard rather than creating a new instance of UserDefaults class. So I think this code
let userDefaults = UserDefaults()
should be replaced with this:
let userDefaults = UserDefaults.standard

Swift 3: Rounding a result embedded in text in a simple calculator

I am absolutely new to Swift 3, my only experience being some basic HTML and JavaScript back in the days before Microsoft FrontPage, Facebook, etc.
I am trying to make a (relatively) simple calculator that will do some math to calculate how much liquid oxygen I would need for patients.
The two problems I am having are that if someone leaves a field blank, the app will crash. The second is that I would like the result to go to one decimal place.
I have found answers about blank fields and rounding, but not my exact example, and I simply get errors that I don't know how to fix.
Please keep in mind that the answers to any questions to me that begin with "Why did you do..." are twofold: 1) because I saw an example like that on the web, and 2) I have no idea what I'm doing.
Code is below.
//
// ViewController.swift
// AECalc
//
// Created by Marco Metzler on 12/31/16.
// Copyright © 2016 Metzler. All rights reserved.
//
import UIKit
import Foundation
class ViewController: UIViewController {
#IBOutlet weak var PTLPM: UITextField!
#IBOutlet weak var LTVVents: UITextField!
#IBOutlet weak var Vents: UITextField!
#IBOutlet weak var EmergLPM: UITextField!
#IBOutlet weak var Ground: UITextField!
#IBOutlet weak var Flight: UITextField!
#IBOutlet weak var LOX: UILabel!
#IBAction func Calculate(_ sender: UIButton) {
let aText = PTLPM.text
let bText = LTVVents.text
let cText = Vents.text
let dText = EmergLPM.text
let eText = Ground.text
let fText = Flight.text
let a = Float(aText!)
let b = Float(bText!)
let c = Float(cText!)
let d = Float(dText!)
let e = Float(eText!)
let f = Float(fText!)
let PtReq = (a! + d!)
let LTVTot = (b! * 20)
let VTot = (c! * 15)
let VentTot = (LTVTot + VTot)
let AllOx = ((VentTot + PtReq) * 60)
let TotTime = (e! + f!)
let answer = ((AllOx * TotTime) / 804)
LOX.text = "LOX required: \(answer) liters."
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//The code below hides the keypad when you tap blank space on the screen. I would prefer to have a "done" button on the keypad.
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Problem #1: Blank Field Causes App Crash
This is because you are force unwrapping optional values with the !:
let aText = PTLPM.text
let a = Float(aText!)
let PtReq = (a! + d!)
This will cause a crash if the text field is empty, or the String cannot be converted to a Float.
Instead, check to see if the values are nil by safely unwrapping them. One way to do this is with some guard statements.
guard let aText = PTLPM.text else {
// handle case where text is nil here
}
guard let a = Float(aText) else {
// handle case where the text is not a valid Float here
}
This will ensure that your variables are actual values before proceeding.
Problem #2: Rounding
This just requires the usage of the String constructor that takes in a format:
LOX.text = String(format: "%.1f", answer)

Running Pace Calculator in Swift

I'm a complete newbie to Swift. I have created a running pace calculator as experiment in Playground and it works perfectly, but I struggle to figure out how to connect it to a UI.
Things in particular I struggle with currently:
Casting a text string to an Int label
Does the function that does the calculation go in the IBAction?
Playground Code
import UIKit
func PaceCalculator (minutes:Double, seconds:Double, distance:Double) -> Double{
return ((minutes*60) + seconds) / distance
}
var paceInSeconds = PaceCalculator(28, 26, 10.1)
var paceInMinutes = paceInSeconds / 60
var roundedMinutes = Double(floor(paceInMinutes))
var decimalSeconds = paceInMinutes - roundedMinutes
var intPace = Int(floor(roundedMinutes))
var seconds = Int(floor(decimalSeconds * 60))
println("Your average pace is \(intPace):\(seconds)/km")
Incomplete Swift Code
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func calculatePaceButton(sender: UIButton) {
}
#IBOutlet weak var minutesTextField: UITextField!
#IBOutlet weak var distanceTextField: UITextField!
#IBOutlet weak var paceLabel: UILabel!
}
Storyboard
Disclaimer: I have no programming experience either. So be gentle on the jargon and explanation.)
Hope this will work for you :
You didn't added secondsTextField as IBOutlet please check that too.
class ViewController: UIViewController {
#IBOutlet weak var minutesTextField: UITextField!
#IBOutlet weak var distanceTextField: UITextField!
#IBOutlet weak var paceLabel: UILabel!
#IBOutlet weak var secondsTextField: UITextField!
#IBAction func calculatePaceButton(sender: UIButton) {
var paceInSeconds = PaceCalculator((minutesTextField.text as NSString).doubleValue, seconds: (secondsTextField.text as NSString).doubleValue, distance: (distanceTextField.text as NSString).doubleValue)
var paceInMinutes = paceInSeconds / 60.0
var roundedMinutes = Double(floor(paceInMinutes))
var decimalSeconds = paceInMinutes - roundedMinutes
var intPace = Int(floor(roundedMinutes))
var seconds = Int(floor(decimalSeconds * 60))
paceLabel.text = "\(intPace)"
}
func PaceCalculator (minutes:Double, seconds:Double, distance:Double) -> Double{
return ((minutes*60) + seconds) / distance
}
}
Here I would like to share my solution to calculate pace. The calculation is based on inputs of times and locations, which are more generic and useful.
typealias ShortFullTupleStrings = (short: String, full: String)
class PaceCalculator {
private static func relatedTimeString(
for value: TimeInterval)
-> ShortFullTupleStrings?
{
let fm = DateComponentsFormatter()
switch abs(value) {
case 0 ..< 24*3600: // within one day
fm.allowedUnits = [.year, .day, .hour, .minute, .second]
case 24*3600 ..< 24*3600*10: // within 1-10 days
fm.allowedUnits = [.year, .day, .hour, .minute]
case 24*3600*10 ..< 24*3600*365: // within 10-365 days
fm.allowedUnits = [.year, .day, .hour]
default: // within 365-1000 days
fm.allowedUnits = [.year, .day]
}
fm.unitsStyle = .short
let short = fm.string(from: value)
fm.unitsStyle = .full
let full = fm.string(from: value)
if let short = short, let full = full {
return (short, full)
} else {
return nil
}
}
static var isMetric: Bool {
let locale = NSLocale.current
let metricSystem = locale.usesMetricSystem
return metricSystem
}
static func paceFrom( _
dt1: Date, to dt2: Date,
distanceFrom loc1: CLLocation, to loc2: CLLocation) ->
ShortFullTupleStrings?
{
let timeInterval = dt2.timeIntervalSince(dt1)
let dist = loc2.distance(from: loc1)
let pace: ShortFullTupleStrings?
if !dist.isZero {
let paceV: TimeInterval
if isMetric {
paceV = timeInterval / (dist / 1000.0)
} else {
paceV = timeInterval / (dist / 1609.344)
}
pace = relatedTimeString(for: paceV)
} else {
pace = nil
}
return pace
}
}
relatedTimeString is a helper func to get a time string in the format of short form of # yrs, # days, # hrs, # min, # sec, and full form of # years, ..., depending on none zero values. For example, 6 min, 5 sec in short form, or 6 minutes, 5 seconds in full form.
In this way, the func is more generic and supports localization and accessibilities.

Could not find '+' that accepts the supplied arguments

I am trying to make a monthly Loan payment calculator
here is the code for it:
import UIKit
class monthlypayment: UIViewController {
#IBOutlet weak var loanamounttextfield: UITextField!
#IBOutlet weak var numberofmonthstextfield: UITextField!
#IBOutlet weak var loanpercentagetextfield: UITextField!
#IBOutlet weak var answerlabel: UILabel!
#IBAction func calculate(sender: AnyObject) {
var loanamounttext = loanamounttextfield.text
var loanamount:Double! = Double((loanamounttext as NSString).doubleValue)
var loanpercentage = loanpercentagetextfield.text
var loanpercentagedouble:Double! = Double((loanpercentage as NSString).doubleValue)
var numbrofmonths = numberofmonthstextfield.text
var numberofmonths:Double! = Double((numbrofmonths as NSString).doubleValue)
var rate = loanpercentagedouble/1200
var monthlypayment:Double = rate+(rate/(1.0+rate)^numberofmonths)-1.0*loanamount
}
}
I get the error here
var rate = loanpercentagedouble/1200
var monthlypayment:Double = rate+ (rate/(1.0+rate)^numberofmonths)-1.0*loanamount
Where numberofmonths and loanamount are doubles as you can see
But I am getting the error:
Could not find '+' that accepts the supplied arguments
In Swift ^ is the XOR operator (which return various flavours of Ints) not the exponential, you want to use the pow(num, power) function instead
var monthlypayment = rate + pow(rate / (1.0 + rate), numberofmonths) - 1.0 * loan amount
Alternatively you can define a custom operator
infix operator ** { associativity left precedence 160 }
func ** (left: Double, right: Double) -> Double {
return pow(left, right)
}
And rewrite your code to a more readable
var monthlypayment = rate + (rate / (1.0 + rate)) ** numberofmonths - 1.0 * loanamount