How divide result from text field to label and get it on another label - swift

I need to finish(Label) = totalAmount(TextField) / adam (Label).
Here is my code:
import UIKit
var plusAndMinus = 0
class ViewController234: UIViewController {
#IBOutlet weak var adam: UILabel!
#IBAction func plus(_ sender: Any) {
plusAndMinus += 1
adam.text = "\(plusAndMinus)"
}
#IBAction func minus(_ sender: Any) {
if(plusAndMinus != 0 ) {
plusAndMinus -= 1
}
adam.text = "\(plusAndMinus)"
}
// Write total amonunt to calculate
#IBOutlet weak var totalAmount: UITextField!
#IBAction func equal(_ sender: Any) {
var adam = 0
var totalAmount = 0
var result = 0
adam = Int(adam)
totalAmount = Int(totalAmount)
guard result != 0 else {return}
result = totalAmount / adam
finish.text = String(result)
}
//Show calculated
// finish = totalAmount / adam
#IBOutlet weak var finish: UILabel!

It looks to me like you are only accessing your local variables and not the text fields in the equal() function.
It is better to use different names for local variables and class properties to avoid confusion.
So first lets validate that the text fields contains values that can be converted to Int variables and otherwise return directly by using guard. Then it's simply a matter of dividing the values but of course we also want to avoid decision by zero so we check that to
#IBAction func equal(_ sender: Any) {
guard let text = Adam.text, let adamValue = Int(text), adamValue != 0,
let totalAmountValue = Int(totalAmount.text!) else { return }
let result = totalAmountValue / adamValue
finish.text = String(result)
}
By using integers we are doing integer division and thus loosing precision, if you want to keep the precision you can switch to Double in the code above and perhaps add some formatting of the result
#IBAction func equal(_ sender: Any) {
guard let text = Adam.text, let adamValue = Double(text), adamValue != 0,
let totalAmountValue = Double(totalAmount.text!) else { return }
let result = totalAmountValue / adamValue
finish.text = String(format: "%.2f", result)
}

I'm not sure what your finish label is because you don't have a label for it, but given that you're meaning to output your answer to it:
enum InputError: Error {
case emptyAdamLabel
case emptyTotalAmountLabel
case divideByZero
case invalidFormat
}
func calculate() throws {
if let adamText = adam.text, adamText.trimmingCharacters(in: .whitespacesAndNewlines) == "" {
throw InputError.emptyAdamLabel
} else if let total = totalAmount.text, total.trimmingCharacters(in: .whitespacesAndNewlines) == "" {
throw InputError.emptyTotalAmountLabel
} else if let adamText = adam.text, adamText == "0" {
throw InputError.divideByZero
} else if let adamNumber = Double(adam.text!), let totalAmountNumber = Double(totalAmount.text!) {
finish.text = String(format: "%.2f", totalAmountNumber / adamNumber)
} else {
throw InputError.invalidFormat
}
}
#IBAction func equal(_ sender: Any) {
do {
try calculate()
} catch InputError.emptyAdamLabel {
print("Adam's label cannot be empty")
} catch InputError.emptyTotalAmountLabel {
print("Total Amount's label cannot be empty")
} catch InputError.divideByZero {
print("Adam's label cannot be zero")
} catch InputError.invalidFormat {
print("Both Adam's label and Total Amount's label have to be integers")
} catch {
print("Unknown errors")
}
adam.text = "0"
totalAmount.text = "0"
}

Related

Saving HighScore in Swift 4

This code has all my labels Im trying to use. I can't save the High score and implement it into the game. Now its saying I need to type more so i'm just going to keep typing until it tells me i'm good. It still hasn't told me i'm goo i'm actually very surprised wow.
import UIKit
import CoreData
import SpriteKit
var timer:Timer?
var seconds:Int = 5
var maxSeconds: Int = 5
var totalPoints:Int = 0
var high:Int = 0
let userDefaults = UserDefaults.standard
let defaults = UserDefaults.standard
class ViewController: UIViewController {
#IBOutlet weak var menu: UIButton!
var i = 0
var point = 0
#IBOutlet weak var highScore: UILabel!
#IBOutlet weak var timeLabel:UILabel?
#IBOutlet weak var points:UILabel?
#IBOutlet weak var totalPoint: UILabel!
#objc func tapped(){
i += 1
switch i {
case 1:
let generator = UINotificationFeedbackGenerator()
generator.notificationOccurred(.error)
case 2:
let generator = UINotificationFeedbackGenerator()
generator.notificationOccurred(.success)
case 3:
let generator = UINotificationFeedbackGenerator()
generator.notificationOccurred(.warning)
case 4:
let generator = UIImpactFeedbackGenerator(style: .light)
generator.impactOccurred()
case 5:
let generator = UIImpactFeedbackGenerator(style: .medium)
generator.impactOccurred()
case 6:
let generator = UIImpactFeedbackGenerator(style: .heavy)
generator.impactOccurred()
default:
let generator = UISelectionFeedbackGenerator()
generator.selectionChanged()
i = 0
}
}
func updateTimeLabel()
{
if(timeLabel != nil)
{
let sec:Int = seconds % 30
let sec_p:String = String(format: "%02d", sec)
timeLabel!.text = "\(sec_p)"
}
}
#objc func onUpdateTimer() -> Void
{
if(seconds > 0 && seconds <= maxSeconds)
{
seconds -= 1
updateTimeLabel()
}
else if(seconds == 0)
{
if(timer != nil)
{
timer!.invalidate()
timer = nil
userDefaults.set(totalPoints, forKey: "totalPoints")
let alertController = UIAlertController(title: "Time Up!", message: "Your time is up! You got a score of \(point) points and your total coins now is \(totalPoints). You Can Do Better", preferredStyle: .alert)
let restartAction = UIAlertAction(title: "Play Again!", style: .default, handler: nil)
alertController.addAction(restartAction)
let FirstSubview = alertController.view.subviews.first
let AlertContentView = FirstSubview?.subviews.first
for subview in (AlertContentView?.subviews)! {
subview.backgroundColor = UIColor(red: 226/255.0, green: 158/255.0, blue: 152/255.0, alpha: 5.0)
subview.layer.cornerRadius = 1
subview.alpha = 1
}
self.present(alertController, animated: true, completion: nil)
point = 0
seconds = maxSeconds
updateTimeLabel()
menu.isHidden = false
defaults.set(high, forKey: "high")
}
}
}
#IBAction func Restart(_ sender: Any) {
}
#IBAction func adder(_ sender: Any)
{
point += 1
points?.text = "\(point)"
if point % 10 == 0 {
totalPoints = 10 + totalPoints
totalPoint?.text = String(totalPoints)
}
if(timer == nil)
{
timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector:#selector(onUpdateTimer), userInfo:nil, repeats:true)
}
tapped()
menu.isHidden = true
}
override func viewDidLoad() {
points?.text = "\(point)"
let total = userDefaults.integer(forKey: "totalPoints")
if total != 0 {
totalPoints = total
} else {
totalPoints = 0
}
let score = defaults.integer(forKey: "high")
if high < point {
high = score
} else {
high = 0
}
totalPoint?.text = String(totalPoints)
updateTimeLabel()
highScore.text = String(high)
}
}
Do I need to put something at the end? Well it looks like that didn't work either!
#for example
func saveHighScore() {
UserDefaults.standard.set(score, forKey: "HIGHSCORE")
}

How can I reuse a variable later on in Swift

I'm trying to capture a user input (textfield + button) and reuse the result later in the program but I don't know how to do that.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var resultLabel: UILabel!
#IBOutlet weak var moneyTextField: UITextField!
#IBAction func convert(_ sender: Any) {
let convertion:Double = Double(moneyTextField.text!)!
print(convertion)
}
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "https://www.x-rates.com/calculator/?from=EUR&to=USD&amount=1")!
let request = NSMutableURLRequest(url : url)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
var rateValue:Double = 0.0;
if let error = error {
print(error)
} else {
if let unwrappedData = data {
let dataString = NSString(data: unwrappedData, encoding: String.Encoding.utf8.rawValue)
var stringSeperator = "<span class=\"ccOutputRslt\">"
if let contentArray = dataString?.components(separatedBy: stringSeperator){
if contentArray.count > 0 {
stringSeperator = "<span"
let newContentArray = contentArray[1].components(separatedBy: stringSeperator)
if newContentArray.count > 0 {
rateValue = Double(newContentArray[0])!
print(newContentArray[0])
}
}
}
}
}
//
print("Rate is \(rateValue)");
DispatchQueue.main.sync(execute: {
self.resultLabel.text = "the value of the dollar is " + String(rateValue)
}
)}
task.resume()
}
}
What I want to do is take the let convertion and multiply it by rateValue at the end of the code. I tried different thing but without any results.
after the advice from Joakim Danielson
I did that :
import UIKit
class ViewController: UIViewController {
var fxRate: Double?
#IBOutlet weak var resultLabel: UILabel!
#IBOutlet weak var moneyTextField: UITextField!
#IBAction func convert(_ sender: Any) {
let convertion:Double = Double(moneyTextField.text!)!
print(convertion)
var convertedAmount = 0.0
if let rate = fxRate, let money = Double(moneyTextField.text) {
convertedAmount = rate * money
}
print(convertedAmount)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = URL(string: "https://www.x-rates.com/calculator/?from=EUR&to=USD&amount=1")!
let request = NSMutableURLRequest(url : url)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
var rateValue:Double = 0.0;
if let error = error {
print(error)
} else {
if let unwrappedData = data {
let dataString = NSString(data: unwrappedData, encoding: String.Encoding.utf8.rawValue)
var stringSeperator = "<span class=\"ccOutputRslt\">"
if let contentArray = dataString?.components(separatedBy: stringSeperator){
if contentArray.count > 0 {
stringSeperator = "<span"
let newContentArray = contentArray[1].components(separatedBy: stringSeperator)
if newContentArray.count > 0 {
rateValue = Double(newContentArray[0])!
print(newContentArray[0])
rateValue = Double(newContentArray[0])!
self.fxRate = rateValue
}
}
}
}
}
//
print("Rate is \(rateValue)");
DispatchQueue.main.sync(execute: {
self.resultLabel.text = "the value of the dollar is " + String(rateValue)
}
)}
task.resume()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
but I have the error : Cannot invoke initializer for type 'Double' with an argument list of type '(String?)' on line 26. Can you please help me? thx!
create a variable outside of your function
var anyVariableYouWantToAccessLater: Double?
And use this variable anywhere you want.
Since you're downloading the rate during viewDidLoad I am assuming this is what you want to keep.
Add a new property to the class
class ViewController: UIViewController {
var fxRate: Double?
...
In viewDidLoad update this property with the downloaded value
rateValue = Double(newContentArray[0])!
fxRate = rateValue
In the convert func (or wherever you want to use the rate)
#IBAction func convert(_ sender: Any) {
var convertedAmount = 0.0
if let rate = fxRate, let money = Double(moneyTextField.text ?? "0") {
convertedAmount = rate * money
}
print(convertedAmount)
}

Swift ViewController Crashes on Load

I'm making a multi conversion tool in iOS to build up my portfolio. However, the distance tab will not load the view. It instantly crashes and gives me two errors.
The second one appears when I try to continue. Below are the errors and my Swift class tied to the controller as well as what the app looks like.
errors
import UIKit
class DistanceViewController: UIViewController, UITextFieldDelegate{
#IBOutlet var userDistance: UITextField!
#IBOutlet var resultLabel: UILabel!
var fromKilometerValue: Measurement<UnitLength>?{
didSet{
milesConversion()
}
}
var fromMileValue: Measurement<UnitLength>?{
didSet{
kilometerConversion()
}
}
override func viewDidLoad() {
super.viewDidLoad()
milesConversion()
kilometerConversion()
}
//Dont forget to drag a gesture recognizer
#IBAction func dismissKeyboard(_sender: UITapGestureRecognizer){
userDistance.resignFirstResponder()
}
let numberFormatter: NumberFormatter = {
let nf = NumberFormatter()
nf.numberStyle = .decimal
nf.minimumFractionDigits = 1
nf.maximumFractionDigits = 1
return nf
}()
func textField(_ userDistance: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
let existingTextHasDecimalSeparator = userDistance.text?.range(of: ".")
let replacementTextHasDecimalSeparator = string.range(of: ".")
if existingTextHasDecimalSeparator != nil,
replacementTextHasDecimalSeparator != nil {
return false
} else {
return true
}
}
var toMileValue: Measurement<UnitLength>?{
if let fromKilometerValue = fromKilometerValue{
return fromKilometerValue.converted(to: .miles)
}
else{
return nil
}
}
var toKilometerValue: Measurement<UnitLength>?{
if let fromMileValue = fromMileValue{
return fromMileValue.converted(to: .kilometers)
}
else{
return nil
}
}
func milesConversion(){
if let toMileValue = toMileValue {
resultLabel.text = numberFormatter.string(from: NSNumber(value: Double(userDistance.text!)!))! + " km" + " is " + numberFormatter.string(from: NSNumber(value: toMileValue.value))! + " miles"
}
}
func kilometerConversion(){
if let toKilometerValue = toKilometerValue{
resultLabel.text = numberFormatter.string(from: NSNumber(value: Double(userDistance.text!)!))! + " miles" + " is " + numberFormatter.string(from: NSNumber(value: toKilometerValue.value))! + " km"
}
}
#IBAction func convertKilometers(_ sender: Any) {
if let input = userDistance.text, let value = Double(input) {
fromKilometerValue = Measurement(value: value, unit: .kilometers)
} else {
fromKilometerValue = nil
}
if(toMileValue == nil){
resultLabel.text = "Unable to Convert " + userDistance.text!
}
}
#IBAction func convertMiles(_ sender: Any) {
if let input = userDistance.text, let value = Double(input) {
fromMileValue = Measurement(value: value, unit: .miles)
} else {
fromMileValue = nil
}
if(toKilometerValue == nil){
resultLabel.text = "Unable to Convert " + userDistance.text!
}
}
}
The class and view are mapped properly from what I see. Anybody have any idea?
EDIT: i had old connections that didnt exist in Main.storyboard, i removed them and the view loads just fine!
Check all of your outlet connections. And read stackoverflow.com/questions/32170456/… – rmaddy

Swift Calculator works perfectly but not when preforming a fresh operation

I have been spending the day today getting familiar with swift and I decided to try to build a calculator. I have the entire thing working except for one issue:
1 + 1 will return 2 to the label (this is fine)
But when I attempt to type a new number, example 1, the string gets appended to 21 instead of clearing the label and placing a singular 1
This occurs because I wanted to add the option for the operators to keep adding ex:
1 + 1 returns 2 then the user types + 3 to get a result of 5
The only issue is I dont know how to clear the label only when a new number is being entered after the equal sign is pressed
Here is the code of the view controller Hopefully I do not have to think of a completely different approach.
import UIKit
class ViewController: UIViewController {
var num1 = ""
var num2 = ""
var finalString = ""
var isFirstNumber = true
var hasFinalString = false
var isClear = true
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBOutlet weak var LBLOutput: UILabel!
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func btrNumberClick(_ sender: UIButton) {
if isClear {
LBLOutput.text = ""
isClear = false
}
let currentText = LBLOutput.text!
let textLabel = sender.titleLabel?.text
if let text = textLabel {
switch text {
case "+", "x", "/", "-","%":
if hasFinalString {
return
}
finalString = text
isFirstNumber = false
hasFinalString = true
LBLOutput.text = "\(currentText) \(finalString) "
break
case "=":
isFirstNumber = true
hasFinalString = false
isClear = true
let result = calculate()
LBLOutput.text = "\(result)"
num1 = "\(result)"
break
default:
if isFirstNumber {
num1 = "\(num1)\(text)"
} else {
num2 = "\(num2)\(text)"
}
LBLOutput.text = "\(currentText)\(text)"
break;
}
}
}
func calculate() -> Double {
let firstNumber = Double(num1)!
let secondNumber = Double(num2)!
num1 = ""
num2 = ""
isClear = false
switch finalString {
case "+":
return firstNumber + secondNumber
case "-":
return firstNumber - secondNumber
case "x":
return firstNumber * secondNumber
case "/":
return firstNumber / secondNumber
case "%":
return (firstNumber * 100) / secondNumber
default:
return 0
}
}
#IBAction func clearTheLabel(_ sender: Any) {
num1 = ""
num2 = ""
LBLOutput.text = "0"
isClear = true
}
}
Why won't this work?
default:
if isFirstNumber {
LBLOutput.text = ""
num1 = "\(num1)\(text)"
LBLOutput.text = num1
} else {
num2 = "\(num2)\(text)"
LBLOutput.text = "\(currentText)\(text)"
}
break;
}
If isFirstNumber is true only after = is pressed then clearing then seems right. I hope I'm understanding your problem.
BTW: The Stanford course with the calculator example hooks all the buttons up to one IBAction as you've done. I think the switch statement is very clear and made for examples like this.

Swift Code Error: Value of type String has no member Int

I'm trying to build a simple calculator in Swift but i can't figure how or why i'm getting the error ("Value of type String has no member type Int") or how to fix it. This is my code so far:
class ViewController: UIViewController {
var isTypingNumber = false
var firstNumber = Int!()
var secondNumber = Int!()
var operation = ""
#IBOutlet weak var calculatorDisplay: UILabel!
#IBAction func acButtonTapped(sender: AnyObject) {
}
#IBAction func number7Tapped(sender: AnyObject) {
let number7 = sender.currentTitle
if isTypingNumber{
calculatorDisplay.text = calculatorDisplay.text! + number7!!
}else{
calculatorDisplay.text = number7
isTypingNumber = true
}
}
#IBAction func divideTapped(sender: AnyObject) {
isTypingNumber = false
firstNumber = calculatorDisplay.text?.Int()! **//Error: Value of type 'String' has no member 'Int'**
operation = sender.currentTitle!!
}
#IBAction func equalsTapped(sender: AnyObject) {
isTypingNumber = false
var result = 0
secondNumber = calculatorDisplay.text?.Int()! **//Error: Value of type 'String' has no member 'Int'**
if operation == "+" {
result = firstNumber + secondNumber
} else if operation == "-" {
result = firstNumber - secondNumber
}else if operation == "X" {
result = firstNumber * secondNumber
}else if operation == "÷"{
result = firstNumber / secondNumber
}
calculatorDisplay.text = "\(result)"
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
firstNumber = 0
secondNumber = 0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Where did i go wrong?
Instead of:
firstNumber = calculatorDisplay.text?.Int()!
You want something like:
if let text = calculatorDisplay.text? {
firstNumber = Int(text)!
}
Or if you want to live on the edge:
firstNumber = Int(calculatorDisplay.text!)!
There is no Int() method in the String type.
To convert an Int to String, try this:
guard let text = calculatorDisplay.text else {
//the CalculatorDisplay has no text, deal with it accordingly
}
guard let firstNumber = Int(text) else {
//the CalculatorDisplay has text, but it's not a valid Int
}
//use firstNumber