newTextField working on simulator but not on iOS7

Please bear with me, this is going to be a very long post.  Please read it all very carefully.

At this point its really hard to tell what the actual problem being reported here is.  I’ve gone back to the top of the thread to try and determine exactly what problem is being reported and frankly it’s a bit hard to know what the real problem is since there seems to be variants of an issue.   To obfuscate this problem some more, there were filed bug reports on the keyboard that engineering did fix post 1202 that seemed to address the reported problems.  Some of it may be related to what was posted here.  It seems that several people on this thread have reported that the post 1202 fixes solved their problems making it hard to know what problems still exist and which ones were solved.

So I was thinking about asking for a very clear example of what was broken so we could separate out what’s been fixed, what Apple fixed between iOS 7 beta and iOS 7 release and so on.  But before I asked for that, I decided to start by taking the code by the OP at the top of the thread, built for my iPhone running 7.0.3 using 1202 and reproduce the problem.   But, with the following code (I had to make the snippet whole):

local serialNumField; local function fieldHandler2( event )     print("Text entered: ".. event.target.text)          if event.phase == "began" then         print("begin")         -- user begins editing textField     elseif event.phase == "ended" then         print("ended")         -- textField/Box loses focus     elseif event.phase == "submitted" then         print("submitted")         -- do something with defaulField's text         native.setKeyboardFocus( nil )     elseif event.phase == "editing" then         print("editing")     end end serialNumField = native.newTextField(0, 0, 400, 60) serialNumField.x = display.contentCenterX serialNumField.y = display.contentCenterY serialNumField.userInput = fieldHandler2; serialNumField:addEventListener ("userInput", fieldHandler2)

I see all of the prints for the appropriate event print as expected.  During the editing phase, event.target.text is one character short.  But in the ended and submitted phases, the string was complete as expected.  In other words, if you’re only taking the string during the editing phase will this actually hurt you.  If you grab it during the “ended” or “submitted” phases like it’s intended, then it works.  I also tested a pre-1202 built app on iOS 7 that did keyboard input and it worked like it supposed to so I could have another reference point.  I had Brent duplicate this on iOS 7.0.2 in case Apple fixed something in 7.0.3.  Unfortunately I have no way of testing 7.0 or 7.0.1.

Brent and I decided to dig further into this.  Next up we took the sample App (and you should always run the sample app’s when you’re having problems) and guess what?  With 1202 on iOS 7 the sample app runs perfectly.  It however is not grabbing the text during the editing phase.  

Brent had some code that was being problematic:

local function editInfo( event )             if event.phase == "began" then                 print("BEGAN")             if event.phase == "ended" or event.phase == "submitted" then                  print("ENDED event.text", event.text)                  native.setKeyboardFocus( nil )             elseif event.phase == "editing" then                  print( "EDITING event.text", event.text )             end end

In this case, during “editing”, it was short and it was the only place he was storing the text value back to his code.  (I’ve modified his code with prints to demonstrate the problem a bit better). Notice he is using event.text not event.target.text.   We learned that event.text is only populated in the event table during the editing phase.  Once it’s submitted, that field is no longer present and it kind of makes sense. 

The event handling code is a complex beast and it’s easy to mix up things.  I’m going to use the term “textField” to reference the actual text field object.  The reason this gets confusing is there is:

textField.text – the actual text of the text field.
event.text – set during the editing phase which is a copy of the textField.text
event.target – which is the actual text field.

The event table changes depending on the phase in question.  During the editing phase, the event table has a copy of the text being edited.  When we get to the submitted phase and the ended phase, we are no longer editing the text, so there is no reason to have event.text populated because the object itself now has the edited (and post-autocorrected) text stored in it.  This is why the Corona SDK sample app works, it’s using the textField’s .text attribute and not depending on the values of the event table.

Changing the code to:

local function editInfo( event )             if event.phase == "began" then                 print("BEGAN")             if event.phase == "ended" or event.phase == "submitted" then                  print("ENDED event.target.text", event.target.text)                  native.setKeyboardFocus( nil )             elseif event.phase == "editing" then                  print( "EDITING event.text", event.text )             end end

 

by using event.target.text in the ended phase, we now get the properly filled out value at the end.  Looking at our sample project for it, we only access the object directly and not the event table, so we always get the right value.

If you are using native.newTextFields directly on the screen and you only care about getting the right value, then only access event.target.text or a direct reference to the object’s .text attribute in the “ended” or “submitted” phases and you shouldn’t have a problem

If you are using the native.newTextField offscreen and are copying the text into an on screen display with display.newText() then you can consider appending event.newCharacters which should have the newly typed characters to the string and see if that helps solve it  If you are doing some type of character count, then add 1.

Now I will qualify this.  Our tests were with Xcode 5 not Xcode 4.6.  If you’re running 1202, you can still build with 4.6 and it’s older iOS SDK’s and that may be contributing to the problem.

If you are still having problems after re-evaluating  your code:

  1. If you can using a later daily build where we have added the iOS 7 bug fixes.

  2. Try it with Xcode 5 installed.

  3. Make sure your accessing the target’s .text field and not the event.text field.

  4. Try the Corona SDK sample app.

If these work arounds are not helpful, please report back with the code you are using.  What you are trying to do?  It might be helpful to know why you’re not using the examples from the Sample project.  Report back what version of Xcode you’re running as well. 

@ Rob Miracle 

Once again, Rob you are the man! Thanks for taking a look at this issue and you couldn’t have put it any more elegantly. Looking at it now, i feel so stupid. I honestly had no idea event.newCharacters was even in the API… But, the issue was using the pseudo-native.newTextField; essentially an text-field located offscreen and grabbing it’s text contents. For me, appending the event.newCharacters worked like a charm. I rewrote it using a editable native.newTextBox earlier trying to do a workaround which failed, but the native.newTextField would act the same. The  only change I made in the editing phase and is in the following two blocks of code. I can confirm that it now works in both the Corona Simulator and Xcode Simulator, as well as, iOS 6.1, 7.0 and 7.03 (don’t have a test device on 7.0.2 ). 

Old

defaultFieldPlaceholder.text = string.sub(defaultField.text, 1 ); 

New

defaultFieldPlaceholder.text = string.sub(defaultField.text .. event.newCharacters, 1 );

Hmmm, sounds like an apology might be in order… All that ends well!  :slight_smile: