How to prevent FormatException from appearing when deleting text from InputField?
I want create to simple date checking functionality using InputFields. I set InputFields to only take integers with 2 to 4 character limit. In Update method i'm checking if it's a leap year, but if I delete the whole number in the box I get FormatException error blocking the app. I use int.Parse() to convert InputField.text to integer and I think there is the problem, because when I delete number there is null. Is there is a way to implement exception, which will not stop the application?
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ButtonDisableTest : MonoBehaviour
{
[Header("Inputs")]
public InputField YearField;
public bool leapYear;
public int intYear;
public void Start()
{
// getting the real date from another script
GameObject Canvas = GameObject.Find("Canvas");
DateTest date = Canvas.GetComponent<DateTest>();
// here i need this or there will be FromatException from the start
YearField.text = date.iYears.ToString();
}
// Update is called once per frame
public void Update()
{
// getting the real date from another script
GameObject Canvas = GameObject.Find("Canvas");
DateTest date = Canvas.GetComponent<DateTest>();
int intYear = int.Parse(YearField.text);
if (intYear % 4 == 0)
{
if (intYear % 100 == 0)
{
if (intYear % 400 == 0)
leapYear = true;
else
leapYear = false;
} else
leapYear = true;
} else
leapYear = false;
}
public void onButtonPressed()
{
Debug.Log("Button pressed" + leapYear);
}
}
Answer by lvskiprof · Feb 18, 2021 at 07:30 PM
Put in a valid date instead of completely clearing it. Just like a BIOS would do, set it to the earliest date you want to handle as a default, or use the current date as a default.
Hey, any idea how can I achieve that?
You can see i use
YearField.text = date.iYears.ToString();
in the Start() method to prevent app crashing on the start. Also I added
if (YearField.text == null)
YearField.text = date.iYears.ToString();
in Update() method and set some integers in Inspector window in the InputFields. But still application crashes.
What is unclear to me is just what your DateTest object is. I am assu$$anonymous$$g that is a class you have created. You find it in both Start and Update, but never use it in this class except where you set the YearField.text in Start(). It would actually be better if you cached what you found in a Class-level reference during Start, so you only look for it the one time instead of 60 times per second in Update().
What is the purpose of finding it in Update() if you don't use it? Assu$$anonymous$$g it can change after Start() runs, you should be setting YearField.text every time in Update() so you can evaluate new values. You also don't need to do the code in Update if the date.iYears.toString() still matches what is in YearField.text. Doing the same code each time when the string has not changed just slows things down. Check to see if it has changed first, if it has you update YearField.text with the new string and evaluate it in Update().
I would actually break out that code into a new function and have Start() always call it and Update() only call it if the iYears string does not match your YearField.text string, while saving the new value in YearField prior to calling the function to check the year.
Basically, you need to make sure that InputField.text is never an invalid year, which means your DateTest object needs to make sure that iYears is never an invalid year. If you are "clearing" YearField.text external to this class (can't tell, but why else is it public?), you should consider removing the public modifier and use a setter function to change it. That function can then verify that what is being set is a valid year value. The same goes for inYear and leapYear. They should be private values within the class that are read by a Get function, so you know that the only place they are modified is in this class.