1

In the pythonista app for iOS I'm trying to check if a textfield in my ui has any numbers in it when I press on a button. When I use the same code on a string it works. When I use the code for textfield within a button's action it doesn't work. Please help? Here's what my code is like:

import ui
import console

def contains_digits(d):
 for char in d:
  if char.isdigit():
   return True
  return False

test='test3'
print(contains_digits(test)) #this works - it prints TRUE!

#below always prints failed even though it should print whatever is in the textfield?!

def button_pushed(sender):
  if contains_digits(textfield1):
   print(textfield1)
  print('failed')

v=ui.load_view()
textfield1 = str(v['textfield1'].text)
v.present('fullscreen')

1 Answers1

2

You’re setting the variable textfield to the field’s text before any text can be entered into the textfield1 TextField.

It will work if you just set textfield1 to v['textfield1'] and then get the .text out of it in your button_pushed function.

def button_pushed(sender):
  if contains_digits(textfield1.text):
   print(textfield1.text)
   return
  print('failed')

v=ui.load_view()
textfield1 = v['textfield1']
v.present('fullscreen')

This works because, instead of setting the text to what is in the field at startup, it waits until you have received notification that the field has been changed (assuming that is when button_pushed is called).

However, the best way to do this is to use the sender variable that button_pushed receives. Assuming you’ve set the TextField up so that textfield1.action is the button_pushed function, sender should be the TextField, so that you can do:

def button_pushed(sender):
  if contains_digits(sender.text):
   print(sender.text)
   return
  print('failed')

(Note that the way button_pushed is set up in your code, it will always print failed even if it also prints the semi-numeric text. You also need a return after the successful printing.)

I am aware of two ways to set a TextField to call a function (or method) as its action in Pythonista. The easiest is probably to set it within your code.

v=ui.load_view()
textfield1 = v['textfield1']
textfield1.action = button_pushed
v.present('fullscreen')

The other method is to set it within the UI file. When you have the TextField selected in the UI editor, and are looking at the settings for the TextField (as I write this, the “i” button in the upper right brings up the settings), the very bottom setting is “CUSTOM ATTRIBUTES”. Set the custom attributes to:

{'action':button_pushed}

Once you make either of these changes, then whenever the text field has finished editing (for example, by pressing “return” or by moving the focus to another field), that action will be called. Of course, if you do this and it turns out to be the behavior you want, you may wish to change the name of the function from button_pushed to something more descriptive of when or why the function is called.

You may also wish to change the name of the TextField from its default of “textfield1” to something more descriptive of its purpose as well, so as to make your code easier to follow once you have multiple fields to work with.

Jerry Stratton
  • 3,287
  • 1
  • 22
  • 30
  • Thanks for this Jerry. It's a great explanation and really helpful. – user1814798 Oct 26 '17 at 09:54
  • 1
    "Assuming you’ve set the TextField up so that textfield1.action is the button_pushed function" - I don't believe I have done this. Would you be able to explain that further for me please? – user1814798 Oct 26 '17 at 09:59