NSNumberFormatter % .PercentStyle symbol not appearing?

(Note. I posted this quesiton yesterday and could not find it today so am trying again.)


My app requires the user to enter four sets of data:

  1. food & drink total (i.e., 125.35)
  2. tax total (i.e., 12.55)
  3. tip preference (ie, 17)
  4. split preference (how many ways the check will be split, i.e., 3)

When the app is first launched the user enters her data. When she enters her tip preference this numeric data is followed by the % symbol per the NSNumberFormatter() code.

I have added a Reset button in the nav bar that the user may use to clear all of the data text fields. My problem is that after the Reset() code is executed the % symbol never appears even though the same exact code is run.

The code that prints out the tip pref (and %) is embedded in textFieldDidEndEditing(...) as follows:


func textFieldDidEndEditing(textField: UITextField) {
     formatter.numberStyle = .CurrencyStyle
     formatter.usesGroupingSeparator = false
     formatter.locale = NSLocale.currentLocale() // This is the default
if textField == foodnDrinkTextField {
     . . .
} else if textField == taxTextField {
     . . .
} else if textField == tipTextField { /
   
            tipTextField.resignFirstResponder()
       
            tipCalc.tipPercentValue = Double((tipTextField.text! as NSString).doubleValue) /
   
            formatter.numberStyle = .PercentStyle
            formatter.maximumIntegerDigits = 3
       
            tipTextField.textColor = UIColor.blueColor() /
            tipTextField.font = UIFont.systemFontOfSize(26, weight: UIFontWeightThin)
       
            /
            tipInput = (tipCalc.tipPercentValue / 100)
            /
            tipTextField.text = formatter.stringFromNumber(tipInput) /
   
        } else if textField == splitTextField {


The Reset() code is as follows:


@IBAction func reset(sender: AnyObject) {

        if tipCalc.tipPrefValue > 100 {

            defaults.removeObjectForKey("foodnDrinkTextField")
            defaults.removeObjectForKey("taxTextField")
            defaults.removeObjectForKey("splitTextField")
     } else {
            defaults.removeObjectForKey("foodnDrinkTextField")
            defaults.removeObjectForKey("taxTextField")
            defaults.removeObjectForKey("tipTextField")/
            defaults.removeObjectForKey("splitTextField")
            defaults.synchronize()  /
        }
     resetFlags() /
      
        navigationController?.navigationBarHidden = true
        foodnDrinkTextField.text = ""   /
        hideAllLabelsnTextFields()      /
    }


In the last set of code you will note the 'defaults.synchronize()' call. I added that thinking that this is what I was missing but that did not help at all.


For the sake of clarity the resetFlags() code has no bearing on the NSNumberFormatter() code so is not included.


My idea for the Reset() function was to enable the user to clear the four data fields when she re-launched the app so she could enter new data. I have no idea why the % symbol will not print since the same exact code is executed after she enters her tip preference.


Any comments or suggestions will be greatly appreciated.


Thanks!

Replies

Can you show us the code that actually resets the fields?

@*****


Thanks for your post.


The Reset() code is the last code set in my post.

I think you should test for identity and not equality everywhere :


if textField === foodnDrinkTextField {
     . . .
} else if textField === taxTextField {
     . . .
} else if textField === tipTextField { /


BTW, is your code just after textField == foodnDrinkTextField { executed as you want

@Claude31


Thanks for your post. I have been trying to resolve this for nearly a month and its driving me nuts.


To answer your question: Let me put it this way, all of the code from textFieldDidEndEditing() produces the result that I expect it to, but the only section of that code that is required to print out an extraneous symbol, ie, the % symbol, is the textField == tipTextField statement code.


I use print stmts to debug with and the SAME EXACT code is executed before or after the Reset button is pressed. This makes absolutely no sense.

====== ..... IN -> touchesBegan() 
... (4)... in touchesBegan() -> tipFlag = false
... (4-C )... in touchesBegan() -> } else { stmt ...


... IN -> textFieldShouldBeginEditing() ...
... LEAVING -> textFieldShouldBeginEditing() ...


====    ... IN -> textFieldDidEndEditing() 
   .... (A) ... in -> textFieldDidEndEditing()  the tip % value is = 0.0
   .... (B) ... in -> textFieldDidEndEditing()  the tipCalc.tipPrefValue is = 100
  in textFieldDidEndEditing() -> (E) in -> else if > textField == tipTextField 
  in textFieldDidEndEditing() -> (E-1) ... TIP TEST (1) > tipTextField.text = Optional("17") 
  in textFieldDidEndEditing() -> (E-2) ... TIP TEST (2) > tipCalc.tipPercentValue = 17.0
  in textFieldDidEndEditing() -> (E-3) ... tipInput TEST ......  tipInput = 0.17 
  leaving textFieldDidEndEditing() -> (E-4) ... 

======  ...  LEAVING in TipperoniViewController -> touchesBegan()


What you see above are the print stmts that follow the


} else if textField == taxTextField {


code. If my NSNumberFormatter() code was such that it would never print out the % symbol I could understand that, but when the app is first launched the % symbol prints out as it should. If the Reset button is pressed and the user re-enters her data the % symbol never appears again.


The code


formatter.numberStyle = .PercentStyle 
    formatter.maximumIntegerDigits = 3


clearly shows that a % symbol is expected and I am allowing three integers. When .maximumIntegerDigits = 2 was accidently used, the % symbol would never print out. Changing that to 3 rectified that, but that is not the problem.


I must be overlooking something very obvious, but it appears that the same exact code is producing different results and that makes no sense whatsoever.


Thanks again for your post.

Could you put a print statement at line 10


} else if textField == tipTextField { / 
    print("I passed here")
            tipTextField.resignFirstResponder()


To see if you execute this part of code on second time ?


Did you try to change == by === ?

@Claude31


Thanks for your post.


I added your print line before I made the '===' change and it printed out to the debug area log as seen here:


============================================================================= 17 entered will tap out
==================== ..... IN -> touchesBegan() 
... (4)... in touchesBegan() -> tipFlag = false
... (4-C )... in touchesBegan() -> } else { stmt ... 
????????????? ... IN -> textFieldShouldBeginEditing() ...................... NEW NEW ...
????????????? ... LEAVING -> textFieldShouldBeginEditing() ...................... NEW NEW ...
====================    ... IN -> textFieldDidEndEditing() 
   .... (A) ... in -> textFieldDidEndEditing()  the tip % value is = 19.0
   .... (B) ... in -> textFieldDidEndEditing()  the tipCalc.tipPrefValue is = 100
  in textFieldDidEndEditing() -> (E) in -> else if > textField == tipTextField


 ... Claude wants to know if this line gets executed


  in textFieldDidEndEditing() -> (E-1) ... TIP TEST (1) > tipTextField.text = Optional("17") 
  in textFieldDidEndEditing() -> (E-2) ... TIP TEST (2) > tipCalc.tipPercentValue = 17.0
  in textFieldDidEndEditing() -> (E-3) ... tipInput TEST ......  tipInput = 0.0 
  leaving textFieldDidEndEditing() -> (E-4) ... 
2016-11-16 10:32:54.025 Tipperoni[9403:8249592] Can't find keyplane that supports type 4 for keyboard iPhone-Portrait-NumberPad; using 563160167_Portrait_iPhone-Simple-Pad_Default
==========  ...  leaving -> TipperoniViewController -> touchesBegan() 
============================================================================= tip=17.  No % value


Your print stmt is on line 12 above.


The results with all of the if/else stmts changed from '==' to '===' are identical.


Here is the actual code showing the '===' change.


} else if textField === tipTextField { /
       
            print("\n  in textFieldDidEndEditing() -> (E) in -> else if > textField == tipTextField \n")
           
            print("\n ... Claude wants to know if this line gets executed\n")
       
            tipTextField.resignFirstResponder()
           
            tipCalc.tipPercentValue = Double((tipTextField.text! as NSString).doubleValue) /
           
            print("  in textFieldDidEndEditing() -> (E-1) ... TIP TEST (1) > tipTextField.text = \(tipTextField.text) \n")
            print("  in textFieldDidEndEditing() -> (E-2) ... TIP TEST (2) > tipCalc.tipPercentValue = \(tipCalc.tipPercentValue)\n")
           
            formatter.numberStyle = .PercentStyle
            formatter.maximumIntegerDigits = 3
           
            tipTextField.textColor = UIColor.orangeColor() /
           
            tipTextField.font = UIFont.systemFontOfSize(26, weight: UIFontWeightThin)
           
            print("  in textFieldDidEndEditing() -> (E-3) ... tipInput TEST ......  tipInput = \(tipInput) \n")
   
            tipTextField.text = formatter.stringFromNumber(Double(tipCalc.tipPercentValue / 100))/
       
            print("  leaving textFieldDidEndEditing() -> (E-4) ... \n")


A brief overview of my app is thus:

I have a dataVC that the user enters her data into: food, tax, tip and split data. When she enters her split data and taps the view the app segues over to the detailVC where all the calculations based on her data are displayed. All of the same data fields that she entered data into in the dataVC are also editable in the detailVC she is currently in. If the tip data is edited the result is ALWAYS followed by the % symbol. The tip code just executed is actually a copy of the same tip code from the dataVC.


Thanks again for your help.

@Claude31


I responded to your post, but I now see that my post is 'Currently being moderated'.


I have no idea ...

a. One difference the second time is that the formatter has been reconfigured "back" from percent to currency, and then gets set to currency a second time. It's possible that not everything is preserved during the round trip from currency to currency. In particular, have you checked whether the value of the "percentSymbol" property of NSNumberFormatter might be different the second time around?


b. You could also trying using two formatters, one for currency and one for percentages. Each would be configured once, then re-used without re-configuration. Of course, you shouldn't have to, but trying it would reduce the number of possible explanations.


c. Why are you setting "maximumIntegerDigits" at all? If setting it to 2 suppresses the percent symbol, then you should at least be suspicious that setting it to 3 suppresses the percent symbol under some set of conditions. Try not setting it.


d. Can you reproduce the problem in a simple test project? That would be a good way to be sure there's not something else interfering, and a good preliminary to a bug report if necessary.

@QuinceyMorris


Thank you very much for your post. This is what I have done:


a. I have checked and double-checked all of the formatter.numberStyle code to insure that only the tip and split data are set to .PercentStyle. The food and tax are set to .CurrencyStyle to insure that they are allowed fractional data entry.


b. If I understand what you are saying, I think I am already doing that. For instance, when the user exits either the food or the tax text fields the code that gets executed contains "formatter.numberStyle = .CurrencyStyle" code. On the other hand, when either the tip or the split text fields are exited from the pertinent code contains "formatter.numberStyle = .PercentStyle" formatting. I hope this what you were suggesting.


c. I commented out the "formatter.maximumIntegerDigits = 3" code in the tip code section and the % symbol still refused to appear after the Reset() button had been pressed.


d. Yes, I can and should code up a test app. I had thought of doing just that but this issue has really consumed all of my time. That said, I will build a test project and see what comes of that.


And one last note before I forget: When the user segues back to the dataVC(the root VC) from the detailVC, dataVC's viewWillAppear() launches as we would expect. This function contains all of the NSNumberFormatter() code to match the data and again, the % symbol is never printed to the view.


I will continue testing.


Thank you again for your insightful suggestions and questions.

Probably you have included a complete URL.


To speed up transmission through the forum, you should remove the https : / / from all URL (even a simple mention of https : / / requires moderator).

@Claude31


I did not include any link in that post. Who knows??


Thanks!

I did not include any link in that post. Who knows??

Back in the day, if the forums software decided that your post looked like spam it would prevent you from posting it at all. A few months ago that changed so that you could make the post but it’d be routed via the moderators. That’s a good thing in general, but it can result in hard-to-understand delays like this one.

OTOH, links will always be routed via the moderators, hence Claude31’s comment.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

@QuinceyMorris

@Claude31


Well, I built and tested a test app that uses both NSUserDefaults and NSNumberFormatter code. I also added a second view similar to my app and coded up two textfields. One textfield was coded for .CurrencyStyle and the other for .PercentStyle. The app behaved perfectly: The .CurrencyStyle printed out "$123.45" and the .PercentSyle printed out "17%", just as expected. This eliminates any suspected bug in Apple's code.


So, while the test app was good practice, it did nothing to resolve my missing % symbol issue. I now believe that the bad behavior begins when I segue back from the detailVC to the dataVC (rootVC). I also know it has nothing to do with Reset() ing or clearing the user NSUserDefault data. I have scoured my viewWillAppear() code because that launches when I segue back. The NSUserDefaults and NSNumberFormatter code works perfectly in the detailVC, but when I segue back to the dataVC the NSNumberFormatter code refuses to work as it should. I know I am overlooking something, but for the time being I have no idea what that may be.


Being the stubborn person that I am, I have spent a lot of time trying to resolve this issue, but I am going to resort to Plan B. Plan B entails using a label with the % symbol and elimnating the NSNumberFormatter code from the tip textfield that produces the % symbol. This issue has been keeping me from submitting the app to the App Store. While it really is a 'cosmetic feature', I still think this issue has to be resolved, but that can wait for an update later on.


Thanks for all of your help.