I am new to the programming world and am trying my hand at a simple math app. Basically i want to app to create two random numbers and then add them together. I then put the answer in a text field where the app checks to see if the answer is right or wrong. I have created this and it works however I cannot get the numbers to regenerate after the answer is correct. Any direction you can give on this I would be much appreciative.
Here is the code.
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.guess(self)
}
#IBOutlet weak var addend1: UILabel!
#IBOutlet weak var addend2: UILabel!
#IBOutlet weak var answer: UITextField!
#IBOutlet weak var response: UILabel!
//create numbers
let newaddend1 = arc4random() % 11
let newaddend2 = arc4random() % 11
#IBAction func guess(sender: AnyObject) {
//Convert Random Numbers to String to be displayed in labels
var firstNumber = String(newaddend1)
var secondNumber = String(newaddend2)
//convert the answer in the text field to an integer
var integer = answer?.text.toInt()
//Convert Strings to Ints so they can be added
var newFirstNumber = firstNumber.toInt()
var newSecondNumber = secondNumber.toInt()
//Add Numbers
var correctAnswer = (newFirstNumber! + newSecondNumber!)
//Display the numbers
addend1.text = firstNumber
addend2.text = secondNumber
//Print correct number to log for test
println(correctAnswer)
println(integer)
//check your answer agains the correct answer
if (integer != nil) {
if (integer == correctAnswer) {
response.text = "Correct! The Answer is \(correctAnswer)!"
} else {
response.text = "Wrongo Bongo the correct answer is \(correctAnswer)!"
}
} else {
response.text = "Please put in a number for your guess"
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//remove keyboard
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
self.view.endEditing(true)
}
func textFieldShouldReturn(textField: UITextField!) -> Bool {
answer.resignFirstResponder()
return true
}
}
You can initialize the variables outside of the IBAction to get class level variable declaration. Then immediately calculate new random numbers once the correct answer is generated:
let newaddend1 = 0
let newaddend2 = 0
#IBAction func guess(sender: AnyObject) {
//Convert Random Numbers to String to be displayed in labels
var firstNumber = String(newaddend1)
var secondNumber = String(newaddend2)
//convert the answer in the text field to an integer
var integer = answer?.text.toInt()
//Convert Strings to Ints so they can be added
var newFirstNumber = firstNumber.toInt()
var newSecondNumber = secondNumber.toInt()
//Add Numbers
var correctAnswer = (newFirstNumber! + newSecondNumber!)
//Display the numbers
addend1.text = firstNumber
addend2.text = secondNumber
//Print correct number to log for test
println(correctAnswer)
println(integer)
//check your answer agains the correct answer
if (integer != nil) {
if (integer == correctAnswer) {
response.text = "Correct! The Answer is \(correctAnswer)!"
let newaddend1 = arc4random() % 11
let newaddend2 = arc4random() % 11
} else {
response.text = "Wrongo Bongo the correct answer is \(correctAnswer)!"
}
} else {
response.text = "Please put in a number for your guess"
}
}
Related
This question already has an answer here:
Limit formatted Measurement to 2 digits
(1 answer)
Closed 4 years ago.
I'm making a temperature slider but the output keeps on displaying 15 or so digits after the decimal place. How do I resolve this and have it display only 4 numbers after the decimal place?
import UIKit
class TemperatureViewController : UIViewController {
#IBOutlet weak var fahrenheitLabel: UILabel!
#IBOutlet weak var celsiusLabel: UILabel!
#IBOutlet weak var kelvinLabel: UILabel!
#IBOutlet weak var temperatureSlider: temperatureSlider!
var temperature:Measurement<UnitTemperature> {
let fahrenheitValue = Measurement<UnitTemperature>(value: Double(temperatureSlider.value), unit: UnitTemperature.celsius)
return fahrenheitValue
}
#IBAction func sliderChange(_ sender: Any) {
updateTemperatureDisplay()
}
func updateTemperatureDisplay() {
celsiusLabel.text = temperature.description
fahrenheitLabel.text = temperature.converted(to: .fahrenheit).description
kelvinLabel.text = temperature.converted(to: .kelvin).description
}
override func viewDidLoad() {
updateTemperatureDisplay()
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
In most cases, you should make use of the available formatters. The measurements API provides a MeasurementFormatter which is a good place to start
let celsius = Measurement<UnitTemperature>(value: 10.91235, unit: UnitTemperature.celsius)
let fahrenheit = celsius.converted(to: .fahrenheit)
let mf = MeasurementFormatter()
mf.unitOptions = .providedUnit
mf.string(from: celsius)
mf.string(from: fahrenheit)
So the above example basically outputs
10.91235 °C // original
51.64222999999585 °F // converted
10.912°C
51.642°F
If you need more control, you can supply your own NumberFormatter to MeasurementFormatter
let numberFormatter = NumberFormatter()
numberFormatter.maximumFractionDigits = 4
numberFormatter.minimumFractionDigits = 2
let mf = MeasurementFormatter()
mf.numberFormatter = numberFormatter
mf.unitOptions = .providedUnit
You could extend Double (and use it throughout your app if this is an operation you need done elsewhere):
extension Double {
func truncate(places: Int) -> Double {
return Double(floor(pow(10.0, Double(places)) * self)/pow(10.0, Double(places)))
}
}
let rawValue = 51.64222999999585
let formattedValue = rawValue.truncate(places: 4)
print(formattedValue) // 51.6422
I'm trying to convert a string into an Int but every time I do it gives me an error.
For example, I have UILabel and it calls resultLabel. Also I have a UITextField.
So what I'm trying to do is first UITextField + second UITextField = resultLabel.
Bottom line, I want from the user to put a number in each UITextField to get the final answer in the resultLabel.
For instance 1 + 1 = 2. But my app gives me 11 or error.
var numberOnScreen:Int = 0
#IBOutlet var first: UITextField!
#IBOutlet var second: UITextField!
#IBOutlet var resultLabel: UILabel!
#IBAction func calculate(_ sender: Any) {
numberOnScreen = Int(first.text!)!
numberOnScreen = Int(second.text!)!
resultLabel.text! = first.text! + second.text!
}
You are doing string concatenation.
First make sure your textfield text are not nil & convert string to int and it can be nil. So you have use if let to make sure the converted values are not nil
if let firstText = firstTextfield.text, let secondText = secondTextfield.text, let firstValue = Int(firstText), let secondValue = Int(secondText) {
let plusValue = firstValue + secondValue
}
First of all if you use + with String, it mean you are concatenating two strings.
So "1" + "1" = "11"
Try it to resolve your problem:
#IBAction func calculate(_ sender: Any) {
guard let first = first.text, let second = second.text, let firstNum = Int(first), let secondNum = Int(second) else {
return
}
let result = firstNum + secondNum
resultLabel.text = String(result)
}
I'm fighting the problem of either having correct calculations (that's awesome) but crashes if I leave a text field blank in the simulator (not awesome) OR: when coded differently, no crashes for blank text fields (not good) but calculates incorrectly (not good).
here's what I'm trying to do:
get user input for 4 values: fibers counted, blank fibers counted (ok if it's zero), fields counted, and sample volume. I put in defaults hoping to take care of any instances where text boxes are blank, hoping to prevent crashes. then the app calculates fiber density, limit of detection, and sample result. pretty simple for now but I hope to add to this later.
My main problem has been optionals. I've read up on that and done my best to code correctly, but there are times when Xcode forces me into a corner. So my app crashes when text fields are blank. or I can prevent crashes but somehow the default values will get used in the calculations and the actual data is off.
I must be using if-let incorrectly, so I tried what you see in the code below.
I'll put the code below, and as always, thanks for any help, and understanding that I'm new and trying to get these concepts down while being self-taught (besides lessons learned here). Thanks!
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var fibersCountedTextField: UITextField!
#IBOutlet weak var blankFibersCountedTextField: UITextField!
#IBOutlet weak var fieldsCountedTextField: UITextField!
#IBOutlet weak var sampleVolumeTextField: UITextField!
#IBOutlet weak var fiberDensityLabel: UILabel!
#IBOutlet weak var limitOfDetectionLabel: UILabel!
#IBOutlet weak var sampleResultLabel: UILabel!
#IBAction func calculateBtnPressed(_ sender: Any) {
var blankCheck: String?
var blankFibersCounted: Double?
var fibersCheck: String?
var fibersCounted: Double?
var fieldsCheck: String?
var fieldsCounted: Double?
var volumeCheck: String?
var sampleVolume: Double?
var sampleResultNumerator: Double?
var sampleResultDenominator: Double?
var sampleResult: Double?
var sampleResultRounded: Double
var fiberDensity: Double
var fiberDensityRounded: Double
var limitOfDetectionNumerator: Double
var limitOfDetectionDenominator: Double
var sampleLimitOfDetection: Double
var sampleLimitOfDetectionRounded: Double
struct TypicalSampleData {
let typicalBlankFibersCounted: Double
let typicalFibersCounted: Double
let typicalFieldsCounted: Double
let typicalSampleVolume: Double
init(typicalBlankFibersCounted: Double = 4.0, typicalFibersCounted: Double = 5.5, typicalFieldsCounted: Double = 100.0, typicalSampleVolume: Double = 555.0) {
self.typicalBlankFibersCounted = typicalBlankFibersCounted
self.typicalFibersCounted = typicalFibersCounted
self.typicalFieldsCounted = typicalFieldsCounted
self.typicalSampleVolume = typicalSampleVolume
}
}
//this code calculates correctly but crashes if text boxes left empty in the simulator.
let defaultSampleData = TypicalSampleData()
//if let blankCheck = blankFibersCountedTextField.text {
// blankFibersCounted = Double(blankCheck)
//} else {
// blankFibersCounted = defaultSampleData.typicalBlankFibersCounted
//}
//blankCheck = blankFibersCountedTextField.text
//var blankCheckDbl: Double?
//if let blankCheck = blankFibersCountedTextField.text {
// blankFibersCounted = Double(blankCheck)
//}; blankFibersCounted = defaultSampleData.typicalBlankFibersCounted
//if let fibersCheck = fibersCountedTextField.text {
// fibersCounted = Double(fibersCheck)
//} else {
// fibersCounted = defaultSampleData.typicalFibersCounted
//}
if blankFibersCountedTextField != nil {
blankCheck = blankFibersCountedTextField.text
} else {
blankFibersCounted = defaultSampleData.typicalBlankFibersCounted
}
if blankCheck == blankFibersCountedTextField.text {
blankFibersCounted = Double(blankCheck!)
} else {
blankFibersCounted = defaultSampleData.typicalBlankFibersCounted
}
if fibersCountedTextField != nil {
fibersCheck = fibersCountedTextField.text
} else {
fibersCounted = defaultSampleData.typicalFibersCounted
}
if fibersCheck == fibersCountedTextField.text {
fibersCounted = Double(fibersCheck!)
} else {
fibersCounted = defaultSampleData.typicalFibersCounted
}
if fieldsCountedTextField != nil {
fieldsCheck = fieldsCountedTextField.text
} else {
fieldsCounted = defaultSampleData.typicalFieldsCounted
}
if fieldsCheck == fieldsCountedTextField.text {
fieldsCounted = Double(fieldsCheck!)
} else {
fieldsCounted = defaultSampleData.typicalFieldsCounted
}
if sampleVolumeTextField != nil {
volumeCheck = sampleVolumeTextField.text
} else {
sampleVolume = defaultSampleData.typicalSampleVolume
}
if volumeCheck == sampleVolumeTextField.text {
sampleVolume = Double(volumeCheck!)
} else {
sampleVolume = defaultSampleData.typicalSampleVolume
}
//if let fibersCheck = fibersCountedTextField.text {
// fibersCounted = Double(fibersCheck)
//}; fibersCounted = defaultSampleData.typicalFibersCounted
//if let fieldsCheck = fieldsCountedTextField.text {
// fieldsCounted = Double(fieldsCheck)
//} else {
// fieldsCounted = defaultSampleData.typicalFieldsCounted
//}
//if let fieldsCheck = fieldsCountedTextField.text {
// fieldsCounted = Double(fieldsCheck)
//}; fieldsCounted = defaultSampleData.typicalFieldsCounted
//if let volumeCheck = sampleVolumeTextField.text {
// sampleVolume = Double(volumeCheck)
//} else {
// sampleVolume = defaultSampleData.typicalSampleVolume
//}
//if let volumeCheck = sampleVolumeTextField.text {
// sampleVolume = Double(volumeCheck)
//}; sampleVolume = defaultSampleData.typicalSampleVolume
//calculate result
if let fibersCounted = fibersCounted, fibersCounted < 5.5 {
sampleResultNumerator = (385 * (5.5 / 100))
sampleResultDenominator = (7.85 * sampleVolume!)
sampleResult = sampleResultNumerator! / sampleResultDenominator!
} else {
sampleResultNumerator = 385 * ((fibersCounted! - blankFibersCounted!) / fieldsCounted!)
sampleResultDenominator = (7.85 * sampleVolume!)
sampleResult = sampleResultNumerator! / sampleResultDenominator!
}
sampleResultRounded = Double(round(1000 * sampleResult!)/1000)
//calculate sample limit of detection
//insert if-let statement here, similar to above?
limitOfDetectionNumerator = 385 * (5.5 / 100)
limitOfDetectionDenominator = (7.85 * sampleVolume!)
sampleLimitOfDetection = limitOfDetectionNumerator / limitOfDetectionDenominator
sampleLimitOfDetectionRounded = Double(round(1000 * sampleLimitOfDetection)/1000)
//calculate fiber density
//insert if-let statement here, similar to above?
fiberDensity = ((fibersCounted! - blankFibersCounted!) / fieldsCounted!) / 0.00785
fiberDensityRounded = Double(round(1000 * fiberDensity)/1000)
fiberDensityLabel.text = String(fiberDensityRounded)
limitOfDetectionLabel.text = String(sampleLimitOfDetectionRounded)
sampleResultLabel.text = String(sampleResultRounded)
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
There are various ways to approach your task, but here is a very straight-forward method (replace fieldA, fieldB, etc with your actual #IBOutlet names):
#IBAction func calculateBtnPressed(_ sender: Any) {
let defaultSampleData = TypicalSampleData()
// get the text from fieldA - set it to "" if fieldA.text is nil
let textA = fieldA.text ?? ""
// get the text from fieldB - set it to "" if fieldB.text is nil
let textB = fieldB.text ?? ""
// if textA CAN be converted to a Double, use it, otherwise use default value
let valA = Double(textA) ?? defaultSampleData.typicalBlankFibersCounted
// if textB CAN be converted to a Double, use it, otherwise use default value
let valB = Double(textB) ?? defaultSampleData.typicalFibersCounted
// set resultLabel.text to the product of valA and valB
resultLabel.text = "Result: \(valA * valB)"
}
The idea being: make sure you have default values for each part of your "equation".
Depending on your actual use-case, of course, you may want to display an Error popup message instead of using default values. But this should get you on your way.
I recently wanted to code an Average-Calculator.
My plan was to build a UITextField in which you can type Numbers separated by commas... By pressing the 'Calculate' button the App should calculate the Average of the Numbers above and give them out by setting a labeltext to the average.
So I wrote my average function and received this error message:
Can not convert value of type 'UITextField' to expected element type 'Double'.
This is my Code:
#IBOutlet var Input: UITextField!
#IBOutlet var Output: UILabel!
#IBAction func Calculate(sender: AnyObject) {
var grades:[Double] = [Input]
func average(nums: [Double]) -> Double {
var total = 0.0
for grade in nums{
total += Double(grade)
}
let gradesTotal = Double(nums.count)
let average = total/gradesTotal
return average
}
let Average = average(grades)
Output.text = "Average: \(Average)"
}
Can you help me with my idea?
Is there a better way to get an input?
You need to separate numbers to get that array if you do that:
you can pass "doubles" array to your average function
code to copypaste :)
var str = "1,2,3,4,5,6"
let stringsWithNumbers = str.componentsSeparatedByString(",")
let doubles = stringsWithNumbers.map { Double($0)! }
Please use lower camel case for variables...
In this line:
var grades:[Double] = [Input]
Input is an instance of UITextField, so you are trying to assign a single-element Array<UITextField> to Array<Double>. You see you cannot do such sort of things.
If you want to accept a text which contains Numbers separated by commas, you need to explicitly convert the text to [Double].
To simplify, let's just ignore the nil or non-numeric values.
Then you need to change your code as:
#IBOutlet var input: UITextField!
#IBOutlet var output: UILabel!
#IBAction func calculate(sender: AnyObject) {
var grades: [Double] = (input.text ?? "").componentsSeparatedByString(",").flatMap{Double($0)}
func average(nums: [Double]) -> Double {
var total = 0.0
for grade in nums{
total += Double(grade)
}
let gradesTotal = Double(nums.count)
let average = total/gradesTotal
return average
}
let averageValue = average(grades)
output.text = "Average: \(averageValue)"
}
The basic idea of this line:
var grades: [Double] = (input.text ?? "").componentsSeparatedByString(",").flatMap{Double($0)}
is well-described in Lu_'s answer. Mine is just a little safer version.
(Addition)
Some explanation about safety:
UITextFields property text is of type String?, so you should think it can be nil. Giving a default value for nil with ?? operator.
And using Double($0)! may crash your app, as Double($0) will return nil for non-numeric strings.
Writing these reminded me one more crash case.
When gradesTotal == 0, the code above will crash with division by zero.
(The default value does not work well for "safety" in the code above...)
So, one more step ahead to safety:
#IBAction func calculate(sender: AnyObject) {
var grades: [Double] = (input.text ?? "").componentsSeparatedByString(",").flatMap{
Double($0.stringByTrimmingCharactersInSet(.whitespaceCharacterSet()))
}
func average(nums: [Double]) -> Double? {
var total = 0.0
for grade in nums{
total += Double(grade)
}
let gradesTotal = Double(nums.count)
if gradesTotal > 0 {
let average = total/gradesTotal
return average
} else {
return nil
}
}
if let averageValue = average(grades) {
output.text = "Average: \(averageValue)"
} else {
output.text = "Average not available"
}
}
What you have to do is using Double(Input.text) instead of [Input]. Right now, you were trying to convert a UITextField to a double, which causes the error.
let textInput = txtInputView.text;
let components = textInput.componentsSeparatedByString(",");
let sum = 0.0;
for txt in components
{
sum = sum + Double(txt);
}
let avg = sum / components.count;
print(avg)
Here is the complete code if someone is interested :)
#IBOutlet var input: UITextField!
#IBOutlet var output: UILabel!
#IBAction func calculate(sender: AnyObject) {
var grades: [Double] = (input.text ?? "").componentsSeparatedByString(",").flatMap{
Double($0.stringByTrimmingCharactersInSet(.whitespaceCharacterSet()))
}
func average(nums: [Double]) -> Double? {
var total = 0.0
for grade in nums{
total += Double(grade)
}
let gradesTotal = Double(nums.count)
if gradesTotal > 0 {
let average = total/gradesTotal
return average
} else {
return nil
}
}
if let averageValue = average(grades) {
output.text = "Average: \(averageValue)"
} else {
output.text = "Average not available"
}
}
#IBAction func userTappedCalculate(sender: AnyObject) { view.endEditing(true)
}
I added the line #IBAction func userTappedCalculate(sender: AnyObject) { view.endEditing(true)
} to close the input TextField when you tap calculate...
I created a small calculator for getting drip rates. Ive managed to get all the fields to multiply to each other, but it won't multiple digits making some calculations short. Im fairly new to coding and have been trying multiple different options. Can someone help me on this? Here is my code:
import UIKit
class DripCViewController: UIViewController {
//outlets/////////////////////////////////////////////////////////////////////////
#IBOutlet var result: UILabel!
#IBOutlet var volume: UITextField!
#IBOutlet var drip: UITextField!
#IBOutlet var time: UITextField!
#IBAction func solve(sender: UIButton) {
//////////////////////////////////////////////////////////////////////////////////
//math functions/////////////////////////////////////////////////////////////////
if let number1 = Int(volume.text!) {
if let number2 = Int(drip.text!) {
if let number3 = Int(time.text!) {
let firstnumber = number1/number3
let secondnumber = firstnumber*number2
result.text = "\(secondnumber) gtts/min"
}
}
}
//////////////////////////////////////////////////////////////////////////////////
//keyboard override feature///////////////////////////////////////////////////////
func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
volume .resignFirstResponder();
drip .resignFirstResponder() ;
time .resignFirstResponder();
}
}
}
You need to use Float or Double instead of Int.
Fixed code:
if let number1 = Double(volume.text!) {
if let number2 = Double(drip.text!) {
if let number3 = Double(time.text!) {
let firstnumber = number1/number3
let secondnumber = firstnumber*number2
result.text = "\(secondnumber) gtts/min"
}
}
}
You are casting the user input to integers. Those are whole numbers without additional precision (eg so only 1, 2 3 etc and not 1.5 and 2.3) You can use a number type that support numbers with more precision like a double.