0

I am trying to make a simple application in Xcode that will calculate digits of Pi to a specific digit (i.e. the 100th digit) and show the time it took to do this. The first step that I am running into is that I want to have a TextField that only accepts an integer value, and when that condition is met, then the button to "start" the program will then be enabled to be pressed. For all other conditions, I would like an error to be thrown saying "Must enter an integer value to continue." but I am having difficulty finding out why this is the case.

I have followed the advice from this thread but I keep getting the error: "Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value" with all of the options that are given.

The only thing I got to compile was the suggestion made by @Naishta all others gave me that error I mentioned before. Here is my code that I have that is able to compile:

    @IBOutlet weak var FirstBox: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()

        //FirstBox.delegate = self
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        guard let _ = Int(string) else {
            button.isEnabled = false
            enum MyError: Error {
                case runtimeError(String)
            }
            return false
        }
        button.isEnabled = true
        return true
    }

and the transition that I am using to go to the next page is just the standard:

@IBAction func StartCalc(_ sender: Any) {
self.performSegue(withIdentifier: "CalcSegue", sender: self)
}

I am expecting to see that when anything besides an integer is written that the button is not able to go to the next page, and for it to throw an​ error.

Robert
  • 153
  • 7
  • what line are you getting that error on? – NSGangster Jun 28 '19 at 18:42
  • @NSGangster I didn’t include the other function I was using to try and do this, but when I did have it enabled the error occurred on the ‘’’ FirstBox.delegate = self ‘’’ line. The function I tried to use was the one suggest by Akbar Khan in the thread I provided. – Robert Jun 28 '19 at 18:47
  • Make sure your outlet is connected to the UITextField. – vacawama Jun 28 '19 at 18:58

2 Answers2

0

Try this one

  func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

        let set = CharacterSet.init(charactersIn: "01234567890").inverted

        if string.rangeOfCharacter(from: set) != nil {

            return false
        }
        button.isEnabled = true

        return true
    }
s4salman
  • 121
  • 6
0

A few things:

  1. If you return false from shouldChangeCharactersInRange the UITextField won't update. If you want the user to type in an invalid input, always return true.

  2. You are only checking the replacement string for Int, if user types 4 with input already text 123 you are only checking if 4 is an int, when maybe you want to check 1234. Even if they hit BACKSPACE, you will be trying to cast an empty string to an Int, which will always fail, return false, and user will never be able to delete a character. I highly recommend you follow this SO post to get full string. And It will look something like.

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    
       let newString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
    
       //now we are comparing the full string, not the replacement string.
       if let _ = Int(newString) {
          button.isEnabled = true
       } else {
           //We can still disable our button and throw runtime error, but still allow text to change.
           button.isEnabled = false
           //You are declaring an enum here, but not throwing an error?
           enum MyError: Error {
               case runtimeError(String)
           }
       }
       return true
    }
    
  3. You can also have your user be more or less prevented (with the exception of a paste operation) from entering a non integer value if you set

    textField.keyboardType = .numberPad

  4. If you use Int the max value your user can add is 2147483647 before it will truncate to the left and you'll get a negative int value. Either check for this, or double the amount / prevent negative value by using an unsigned int UInt. Even better if you want HUGE numbers, UInt64 would give you 0 to 18,446,744,073,709,551,615. For more info on the different types of integer's in swift check this out.

  5. You may be getting a runtime error for nil object reference if your UITextView outlet is not properly connected from storyboard.

NSGangster
  • 2,397
  • 12
  • 22