Function in textFieldDidEndEditing is running when it’s not supposed to run - swift

I've got 5 text fields:
When I type values in any 4 of the text fields, the value should be calculated and it should appear in the 5th text field.
For example, if I enter values in the Interest, Monthly Payment, Future Value and Number of Payments text fields, a value should be calculated and it should appear on the Principal Amount text field.
The calculation takes place when the Keyboard is dismissed (textFieldDidEndEditing).
Here is the code for that:
// When the user has finished typing
func textFieldDidEndEditing(_ textField: UITextField) {
// Principal Amount
let P = Double(principalAmountTextField.text!)
// Interest rate
let r = Double(interestTextField.text!)
// Monthly Payment
let PMT = Double(monthlyPaymentTextField.text!)
// Number of Payments
let t = Double(numOfPaymentsTextField.text!)
// Future Value
let A = Double(futureValueTextField.text!)
// Check if the necessary text fields are filled to find Principal Amount
if futureValueTextField.text != "" && interestTextField.text != "" && numOfPaymentsTextField.text != "" && monthlyPaymentTextField.text != "" {
print(1)
principalAmountTextField.text = String(calculatePrincipalAmountCompound(futureValue: A!, interestRate: r! / 100, payment: PMT!, numOfPayments: t!))
}
// Check if the necessary text fields are filled to find Monthly Payment
if futureValueTextField.text != "" && principalAmountTextField.text != "" && numOfPaymentsTextField.text != "" && interestTextField.text != "" {
print(2)
monthlyPaymentTextField.text = String(calculateMonthlyPaymentCompound(principalAmount: P!, futureValue: A!, numOfPayments: PMT!, interestRate: r! / 100))
}
}
So clearly, if I enter values in the Interest, Monthly Payment, Future Value and Number of Payments text fields, only the first IF condition in the textFieldDidEndEditing method should run, but for some reason, the second IF condition runs too. Why does this happen?
Edit
Thanks to #tomerpacific I was able to make this work. But I still don't know why the above code doesn't work, I just tried running the IF conditions without calling the methods and it works properly:
// Check if the necessary text fields are filled to find Principal Amount
if futureValueTextField.text != "" && interestTextField.text != "" && numOfPaymentsTextField.text != "" {
print(11)
}
// Check if the necessary text fields are filled to find Monthly Payment
if futureValueTextField.text != "" && principalAmountTextField.text != "" && numOfPaymentsTextField.text != "" && interestTextField.text != "" {
print(22)
}

The problem lies with your logic.
Let's break it down to make things clearer.
if futureValueTextField.text != "" && interestTextField.text != "" && numOfPaymentsTextField.text != "" && monthlyPaymentTextField.text != "" {
print(1)
principalAmountTextField.text = String(calculatePrincipalAmountCompound(futureValue: A!, interestRate: r! / 100, payment: PMT!, numOfPayments: t!))
}
When this if condition is true, principalAmountTextField gets a value.
So, after this condition, the following text fields have values:
futureValueTextField
interestTextField
numOfPaymentsTextField
monthlyPaymentTextField
principalAmountTextField
// Check if the necessary text fields are filled to find Monthly Payment
if futureValueTextField.text != "" && principalAmountTextField.text != "" && numOfPaymentsTextField.text != "" && interestTextField.text != "" {
print(2)
monthlyPaymentTextField.text = String(calculateMonthlyPaymentCompound(principalAmount: P!, futureValue: A!, numOfPayments: PMT!, interestRate: r! / 100))
}
Now, since you don't return from your if clauses or don't have an if/else flow, the next if evaluates to true when the following textfields have values:
futureValueTextField
interestTextField
numOfPaymentsTextField
principalAmountTextField
And since you have given principalAmountTextField a value, the second if condition is met and the code runs.

Related

EF Core - detect actual property value changes

I'm attempting to detect which fields/properties/columns have changed in DbContext's SaveChanges() method. I'm currently using the following code:
string fields = "";
foreach (var entityProperty in ent.Entity.GetType().GetProperties())
{
var propertyName = entityProperty.Name;
var currentValue = ent.Property(propertyName).CurrentValue;
var originalValue = ent.Property(propertyName).OriginalValue;
if ( currentValue == null && originalValue != null ||
originalValue == null && currentValue != null ||
(currentValue != null && originalValue != null &&
!originalValue.Equals(currentValue))
)
{
fields += propertyName + ", ";
}
}
My code frequently sets the values of columns to their current value so I can't rely on PropertyEntry.IsModified - that seems to get set to true even if you set a field to the same value it already has.
Also, in the above code, originalValue is coming out as the NEW value of the column, so this code isn't working either.
Does anyone know how I can detect which fields/properties/columns have actually had their value changed?

Is there any way to chain optional assignment unwrapping into if conditional in Flutter, the way it is like Swift?

In Swift, there's a simple language feature to chain unwrapping and checking for non null like this:
if let data = functionReturningNullableNumber(), data != 0 { processNum(data) }
if let data = functionReturningNullableString(), data != "" { processStr(data) }
In Flutter, currently I have to do this:
var dataNum = functionReturningNullableNumber();
if (dataNum != null && dataNum != 0) { processNum(dataNum); }
var dataStr = functionReturningNullableString();
if (dataStr != null && dataStr != "") { processStr(dataStr); }
Is it possible to create something similar to the Swift above? Especially the part where I can assign a temporary variable name that will disappear outside of the if scope, so I can reuse the variable name.
Of course I can do this:
if (functionReturningNullableNumber() != null && functionReturningNullableNumber() != 0) { process(functionReturningNullableNumber()); }
But this isn't what I'm searching for.

How to check if a string is a character in Swift

I have a textField (symbolTextField), I will input character to the textField. And only characters will be accepted in the textField. So I need to check if the input has a single character in the textField.
I have a button, I am updating the button state, when the symbolTextField has only one character instead of several characters (String), then the button will be enabled.
I am thinking about to add one more condition in the "saveButton.isEnabled = " to check if symbolTextField.text is a character, how can I do that?
func updateSaveButtonState() {
let symbolText = symbolTextField.text ?? ""
let nameText = nameTextField.text ?? ""
let descriptionText = descriptionTextField.text ?? ""
let usageText = usageTextField.text ?? ""
saveButton.isEnabled = !symbolText.isEmpty && !nameText.isEmpty && !descriptionText.isEmpty && !usageText.isEmpty
}
Assuming is a character means is one character just count the characters
By the way UITextField has a hasText property which reduces the code considerably.
func updateSaveButtonState() {
saveButton.isEnabled = nameTextField.hasText &&
descriptionText.hasText &&
usageTextField.hasText &&
symbolTextField.text!.count == 1
}

Form validation issue in macOS app

I am trying to run through a settings form and make sure that the user hasn't left any of the required fields empty.
Some of the forms fields are secure ( eg password).
Whats the easiest way to loop through all these fields and check they are not empty?
I have tried below - but I get a weird error:
if textfield1.stringValue == "",
textfield2.stringValue == "",
passwordfield.stringValue == "" {
//Shows error: Braced block of statements is an unused closure
}
Additionally I am unable to group all these NSTextfields into an array as the password textfields are NSSecureTextField which despite being inherited from NSTextfield, the are not groupable with NSTextfield.
You can have NSTextField and NSSecureTextField in the same array. This is indeed an easy way to find the empty ones.
let tf = NSTextField()
let stf = NSSecureTextField()
let tf2 = NSTextField()
tf2.stringValue = "some text"
let all = [tf, stf, tf2]
let emptyTextFields = all.filter { $0.stringValue.isEmpty }
Also in your example you can't use commas to group conditions in if, you have to use &&:
if tf.stringValue.isEmpty && stf.stringValue.isEmpty && tf2.stringValue.isEmpty {
// do something
}
but this is not a good solution, better use the array and filter.
Under Swift 2, here's what Eric Aya correctly identified:
if textfield1.stringValue == "" && textfield2.stringValue == "" && == "" {
}
It also compiles under Swift 3.
On the other hand, the code you put in your question actually works in Swift 3.
Other way to check empty string with isEmpty variable of String object.
let userName = ""
let email = ""
if(userName.isEmpty && email.isEmpty) {
print("empty strings")
}
else {
print("good strings")
}

Checking multiple conditions for a string in C#

I want to check multiple conditions in a string in C# but it throws error saying Cannot use && for string or boolean
if ((duStart.Trim() != "" && duStart.Trim() != null) &&(duEnd.Trim() != "" && duEnd.Trim() != null))
{
//do this
}
else
//do that
The code you've given compiles fine. Here's a short but complete program - I've changed the whitespace of your line of code, but that's all:
using System;
class Test
{
static void Main()
{
string duStart = "X";
string duEnd = "X";
if ((duStart.Trim() != "" && duStart.Trim() != null) &&
(duEnd.Trim() != "" && duEnd.Trim() != null))
{
Console.WriteLine("Yes");
}
}
}
Having said that:
If you're going to use the same value (the trimmed version of duStart, for example) multiple times, there seems little point in computing it twice. I'd have used extra local variables (trimmedStart, trimmedEnd) here
Trim never returns null, so those tests are pointless.
Using string.IsNullOrWhitespace is probably a better idea here. Why bother creating strings that you're never going to use?
you can simplify the condition by writing:
if( !string.IsNullOrEmpty(duStart.Trim()) && !string.isNullOrEmpty(duEnd.Trim()) )
{
}
Check for the Null first for duStart and duEnd. Then try Trim the string. Trim cannot be applied on a null value. So, below code block should work for you.
if ((duStart != null && duStart.Trim() != "") && (duEnd != null && duEnd.Trim() != ""))
{
//do this
}
else
{
//do that
}