When is a UITextField's text property set? - objective-c

I've been having an interesting problem. I've got both a UIButton and a UITextField, lets call them myButton and myField respectively. Now, when the user presses myButton, it is supposed to save the contents of [myField text] to another variable that we'll call otherVar. Now when I type into myField and hit the return key, everything works fine, however when I press myButton before myField has been left, the string that gets stored in otherVar always looks something like:
<UIButtonContent: 0x4e13c60 Title = (null), Image = <UIImage: 0x4b50980>, Background = (null), TitleColor = UIDeviceWhiteColorSpace 1 1, ShadowColor = UIDeviceWhiteColorSpace 0 0.5>
Does the [myField text] not get set until the user presses the return key, leaving the text field? And also, is there a way to tell if the user has left myField before pressing myButton?
Here is the IBAction code for myButton:
-(IBAction)myButton:(id)sender{
if (![[myField text] isEqualToString:#""]) {
[[[appDelegate moduleList] objectAtIndex:[appDelegate moduleNum]] setOtherVar:[myField text]];
}
}
thanks!

Try adding [myField resignFirstResponder]; before your if statement in the IBAction method. This should commit any of the text edits that have been made, and populate the text property.

You can use notifications to know exactly when a UITextField has changed its value, discussed in the docs here.
More about notifications here.
There are also delegate methods for UITextFields which let you know when editing begins and ends, among other things - docs here.

Related

Update property bound from text field without needing to press Enter

I have a text field and I bind it to an NSString instance variable.
When I type in the text field, it does not update the variable. It waits until I press the Enter key. I don't want to hit Enter every time.
What do I need to change in order to make the binding change value immediately?
By default, the value binding of an NSTextField does not update continuously. To fix this, you need, after selecting your text field, to check the "Continuously Updates Value" box in the Bindings Inspector under the Value heading:
However, most often, what you really want to do is update the property to which the text field is bound when the user has finished editing and presses a button ("Save" or "OK", for example). To do this, you needn't continuously update the property as described above, you just need to end editing. Daniel Jalkut provides an extremely useful implementation of just such a method:
#interface NSWindow (Editing)
- (void)endEditing;
#end
#implementation NSWindow (Editing)
- (void)endEditing
{
// Save the current first responder, respecting the fact
// that it might conceptually be the delegate of the
// field editor that is "first responder."
id oldFirstResponder = [oMainDocumentWindow firstResponder];
if ((oldFirstResponder != nil) &&
[oldFirstResponder isKindOfClass:[NSTextView class]] &&
[(NSTextView*)oldFirstResponder isFieldEditor])
{
// A field editor's delegate is the view we're editing
oldFirstResponder = [oldFirstResponder delegate];
if ([oldFirstResponder isKindOfClass:[NSResponder class]] == NO)
{
// Eh ... we'd better back off if
// this thing isn't a responder at all
oldFirstResponder = nil;
}
}
// Gracefully end all editing in our window (from Erik Buck).
// This will cause the user's changes to be committed.
if([oMainDocumentWindow makeFirstResponder:oMainDocumentWindow])
{
// All editing is now ended and delegate messages sent etc.
}
else
{
// For some reason the text object being edited will
// not resign first responder status so force an
/// end to editing anyway
[oMainDocumentWindow endEditingFor:nil];
}
// If we had a first responder before, restore it
if (oldFirstResponder != nil)
{
[oMainDocumentWindow makeFirstResponder:oldFirstResponder];
}
}
#end
So if for example you had a "Save" button targeting your view controller's method -save:, you would call
- (IBAction)save:(id)sender
{
[[[self view] window] endEditing];
//at this point, all properties bound to text fields have the same
//value as the contents of the text fields.
//save stuff...
}
The previous answer is beautiful, and I learned from it about tricking the Window/View/Document system to end-editing on everything at the programmer's will.
However, the default responder chain behavior (including the preservation of the first responder until the USER moved their focus to something else) is fundamental to the Mac's "look and feel" and I wouldn't mess with it lightly (I swear I did very powerful things in responder-chain manipulation, so I don't say that out of fear.)
In addition - there is even a simpler method - that does not require changing the binding. In the Interface-builder, select the text field, and select the "Attribute Inspector" tab. You'll see the following:
Checking the red-circled "continuous" will do the trick. This option is basic and older even than binding, and its main use is to allow validator object (a whole new story) to validate the text and change it on the fly, as the user types. When the text-field calls validator calls, it also updates bound values.

Why can I not reset a text field within an IBAction associated with it?

I have an IBAction called keyboardResponse associated with a text field called myTextFieldIBOutlet via the "Editting Changed" event handler in the xib:
- (IBAction)keyboardResponse:(id)sender
{
// process this single character - function I wrote else where that works fine.
[self processSingleCharacter:myTextFieldIBOutlet.text];
// clear input text
myTextFieldIBOutlet.text = #"";
}
It's supposed to clear the input after the user types something into it.
I get a run time error with this code in iOS Simulator:
Thread 1: EXC_BAD_ACCESS (code=2, address=0xbf7fff0c)
Why? I had synthesized the IBOutlet myTextFieldIBOutlet already.
if myTextFieldIBOutlet is synthesized, you should change the last line to:
self.myTextFieldIBOutlet.text = #"";
If the textfield you want to clear is the same control that calls this action, you can also use the sender variable you are sending
[sender setText:#""];

How can I manually enable or disable the Return Key on the keyboard?

I have a UITextView that receives input from the keyboard. The "Auto Enable Return Key" checkbox is checked, so when the UITextView is empty the Return key is disabled.
I have an Emoticons bar above the keyboard that can add emoticons to the UITextView as well, but here's the problem; When the UITextView is empty and I add an emoticon to the UITextView like this:
[inputTextView insertText:#"\ue40d"];
then the ReturnKey is still disabled, although the UITextView's text property is not empty.
I've tried this after inserting an emoticon:
[inputTextView setEnablesReturnKeyAutomatically:NO];
With no results. It looks like enabling/disabling the Return Key of the keyboard is only triggered by entering characters through the keyboard.
Any idea's how to do manually enable/disable the Return key?
It's a bit of a hack, but you could try inserting the text via the pasteboard instead:
UIPasteboard* generalPasteboard = [UIPasteboard generalPasteboard];
// Save a copy of the system pasteboard's items
// so we can restore them later.
NSArray* items = [generalPasteboard.items copy];
// Set the contents of the system pasteboard
// to the text we wish to insert.
generalPasteboard.string = text;
// Tell this responder to paste the contents of the
// system pasteboard at the current cursor location.
[textfield paste: nil];
// Restore the system pasteboard to its original items.
generalPasteboard.items = items;
// Free the items array we copied earlier.
[items release];
You can use
textField.setValue(isEnabled, forKeyPath: "inputDelegate.returnKeyEnabled")
Fox example inside
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
uncheck "Auto Enable Return Key"

Change label text based on textfield

I'm making a little demo app and I'm having trouble changing.
Heres the thing:
I have a UIButton that every click will add a character in a NSString in a UITextField.
And I put an IBAction(Mudar_Resposta) on that UITextField(campo) in the part 'Value Changed'.
In that IBAction, I put that:
- (IBAction)MudarResposta:(id)sender {
campo.text=#"lol";
}
But I can't get it to work. Any ideas?
Thanks.
The proper way to get it to work is to connect an action method to the Touch Up Inside event for your button. Within that method, edit they text for your text field.
- (IBAction)mudarResponsta:(id)sender { // Connect to Touch Up Inside of your button
campo.text = [NSString stringWithFormat:%# %#", campo.text, #"lol"]; // Add string ' lol' every time it's called
}
Connecting to Value Changed will never invoke the method because the value is never being changed—you're connecting the changing method to the change…if that makes any sense.
Most likely you didn't connect that action to anything in the XIB file.
- (IBAction)Button:(id)sender {
[self.contacts addObject:_txtField.text];
_txtField.text=#"";
}
Here contacts is an Array name which is a Mutable Array. txtField is UITextField.

NSTextField delegate notifications -- how to get text?

I've been trying to learn to use Xcode, but I'm getting confused with how to register that NSTextField has changed. Essentially, I have an NSTextField and a button. Clicking the button does stuff with the text in the field. However, I want to be able to get the text of the field without needing to use the text field "Action:send on end editing." That is, I want to be able to enter text and immediately press the button, without hitting enter or tabbing out of the text box. It seems like the way to do this would be by setting a delegate for my NSTextField that responds to
- (void)controlTextDidChange:(NSNotification *)aNotification
But I don't understand how to get the text that has been entered. I assume it has something to do with
[[aNotification userInfo] valueForKey:#"NSFieldEditor"];
but I really have no idea where to go from there.
You're on the right track! The object that you get out of the notification's user info dictionary is the Field Editor, which is simply an NSTextView that's handling the text input on the text field's behalf.
Once you have that object, all you have to do is ask it for its textStorage, which is an NSTextStorage* object holding the text. That object, in turn, has its string which is a plain old NSString holding just the characters.
NSTextView * fieldEditor = [[aNotification userInfo] objectForKey:#"NSFieldEditor"];
NSString * theString = [[fieldEditor textStorage] string];
*A subclass of NSAttributedString, which is an object holding a string and associated "attributes" like color, font, and underlining.
In your button action method, simply read the current string value in the text field:
- (IBAction)didClickTheButton:(id)sender {
NSString* theString = [myTextField stringValue];
// do something with theString
}
If you're only ever handling a single text field, this may be simpler:
- (void)controlTextDidChange:(NSNotification *)obj {
[self.inputField stringValue];
}
I'm totally ignoring all the complicated details of NSText and whatnot and just using the simplicity of the notification being sent and the simplicity of getting the string value from a text field.