Click textfield and button disappears (it doesn't, but i want it to) - uibutton

I have a textfield and a button. When I click inside the textfield, I want the button to disappear. I defined the textfield as both outlet and action ( with event “Did end on exit”). In the method for the textfield, I have self.testButton.hidden = YES; When I click inside the textfield, the button does not go away. Instead, it remains until I hit the return key on the keyboard – causing the keyboard to go away. I tried the same thing w/ touchup inside as the event on the text field. When you click in the text field, nothing happens to the button.

Instead of using the Target-Action mechanism ("Did end on exit" and "Touch Up Inside") use the Delegate mechanism.
First, make your class conform to the UITextFieldDelegate protocol. In your *.h (header) file add the following:
// Here I'm assuming your class is inheriting from UIViewcontroller but it
// may be inheriting from some other class. The really important part here
// is: <UITextFieldDelegate>. That's how you make your class conform to that protocol
#interface THE_NAME_OF_YOUR_CLASS : UIViewController <UITextFieldDelegate>
.
Second, implement the -(void)textFieldDidBeginEditing:(UITextField *)textField method. Also, remember to set yourself as the delegate too: self.textField.delegate = self. That way, the method will get called every time the user starts editing. Inside that methdod call self.testButton.hidden = YES;. In your *.m (implementation) file add the following:
-(void)viewDidLoad {
// here I'm assuming you have a 'strong' reference to your text field.
// You're going to need one to set yourself as the delegate.
self.textField.delegate = self;
}
// This is one of the methods defined in the UITextFieldDelegate protocol
-(void)textFieldDidBeginEditing:(UITextField *)textField {
self.testButton.hidden = YES;
}
.
Similarly, to make your button appear again, implement the - (void)textFieldDidEndEditing:(UITextField *)textField method. Inside it un-hide your button. Again, in your *.m file add the following:
// This is another method defined in the UITextFieldDelegate protocol
-(void)textFieldDidEndEditing:(UITextField *)textField {
self.testButton.hidden = NO;
}
Although delegates may be a mystery to you right now once you become familiar with them
you will realize they're very easy. And this is very important because iOS programming
relies heavily on delegates.
A delegate is a "notification" mechanism based on the "Hollywood" principle which is: don't call us; we'll call you.
In your case the class that contains the UITextField is interested in knowing when the UITextField begins editing and when it ends editing. But your class cannot be "polling" (that is, constantly asking) the text field to find out if the state changed. Instead you register your class with the text field and it will be the text field the one that will let you know when something happened. That will be thanks to the methods that you implemented.
Further reading: protocols and delegates
Hope this helps!

Have you made sure that testButton has its IBOutlet set before you hide it?

If you want to button to disappear when the user begins editing the text field, try UIControlEventEditingDidBegin.

Related

NSWindow, press key ENTER: how to limit the key listening to the focused NSControl?

I have an NSWindow with a main "OK" button. This button has as "key equivalent" property in interface builder, the key ENTER i.e ↵.
It works good, but now I have a new NSComboBox, which is supposed to invoke a method when the user selects a list item, or he preses Enter / ↵.
However, when I press Enter, the main Button receive the notification and the window close. How to prevent this?
This is the normal behavior what you are getting, but you can hack a bit, by removing and adding the key-equivalent.
Add following delegates of NSComboBox:
- (void)comboBoxWillPopUp:(NSNotification *)notification;{
[self.closeButton setKeyEquivalent:#""];
}
- (void)comboBoxWillDismiss:(NSNotification *)notification;{
[self.closeButton setKeyEquivalent:#"\r"];
}
One way you can workaround for prevent enter notification is like that below:-
//Connect this action method to your combobbox and inside that set one BOOL flag to yes
- (IBAction)comBoxItm:(id)sender
{
self.isEnterCalled=YES;
}
//Now check this flag to your some method where close window is called
-(void)someMethod
{
//Check the flag value if it is yes then just ignore it
if (!self.isEnterCalled)
{
//Close window logic
}
self.isEnterCalled=NO;
}
Ran into the same problem. Had "hot key" which I'd like to switch off while editing some text fields. I found solution for myself. There's no need in override lots of NSTextField base methods.
Firstly, I removed all the "key equivalents". I used to detect Enter key down with the + (void)addLocalMonitorForEventsMatchingMask:(NSEventMask)mask handler:(NSEvent *(^)(NSEvent *))block class method of NSEvent. You pass block as a parameter, where you can check for some conditions. The first parameter is the event mask. For your task it would be NSKeyDownMask, look for other masks at the NSEvent Reference Page
The parameter block will perform each time the user pushes the button. You should check if it is right button pushed, and - generally - if the current window first responder isn't some editable control. For that purposes we need NSWindow category class just not to implement this code each time we deal with NSKeyDownMasked local monitors.
NSWindow+Responders class listing:
#interface NSWindow (Responders)
- (BOOL)isEditableFirstResponder;
#end
#implementation NSWindow (Responders)
- (BOOL)isEditableFirstResponder
{
if (!self.firstResponder)
return NO; // no first responder at all
if ([self.firstResponder isKindOfClass:[NSTextField class]]) // NSComboBox is NSTextField subclass
{
NSTextField *field=(NSTextField *)self.firstResponder;
return field.isEditable;
}
if ([self.firstResponder isKindOfClass:[NSButton class]]) // yep, buttons may be responders
return YES;
return NO; // the first responder is not NSTextField or NSButton subclass - not editable
}
#end
Don't know if there's another way to check if we are now editing some text field or combo box. So, there's at least the part you add the local monitor somewhere in your class (NSWindow, NSView, some controller etc.).
- (void)someMethod
{
id monitor=[NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask handler:(NSEvent *)^(NSEvent *theEvent){
if (theEvent.keyCode==/*Enter key code*/ && ![self.window.isEditableFirstResponder]) // you should check the key modifiers too
{
// your code here
}
return theEvent; // you may return the event to pass the key to the receiver
}];
}
Local monitors is safe remedy about the Apple rules. It works only inside your application. For global key down events you may use addGlobalMonitor but Apple may reject your app from the AppStore.
And don't forget to remove the monitor when there's no need in it.
- (void)viewControllerShutdownMethod
{
[NSEvent removeMonitor:monitor];
}
Good luck.

NSTextField Subclass textDidEndEditing: Deleting Text

I have an NSTextFeild Subclass in which I would like to implement textDidEndEditing: to check after each edit if it is empty or not. The method is being called perfectly, but when I click into another NSTextField (or a subclass), all the text that was in the first textfield is immediately deleted. If I click out into the view, the text stays, but is deleted the next time i click into another textfeild. All I have in the method right now is an NSLog. Does anyone have any ideas as to why this could be happening?
#import "BufferTableCellViewTextField.h"
#implementation BufferTableCellViewTextField
- (void)textDidEndEditing:(NSNotification *)notification{
NSLog(#"END");
}
#end
You need to call -super:
- (void)textDidEndEditing:(NSNotification *)notification;
{
[super textDidEndEditing:notification];
NSLog(#"END");
}
This delegate method wouldn't be causing your problem. I'd look back to your subclass and check to see that you are not using any UITextField delegate methods that are expecting a YES response that you may have inadvertently changed the return responses for. It may be helpful to post you subclass so we can see what is going on in there too...

Xcode - setFocus on a text field, becomeFirstResponder isn't enough

At the moment, I trigger a method on 'Did End On Exit' in my app (I'm aware that this may not be the greatest way of doing it but I'm very new to Objective C and Xcode for that matter and I'm simply doing what feels comfortable to me).
This method resigns the firstResponder from the current text field and applies it to a later text field.
The problem I'm facing is that the keyboard covers the next text field so that the use has no idea where the focus is and therefore what they are required to type.
How do I get it so that my keyboard shifts down and actually shows the text box that is currently active? Making something the firstResponder simply doesn't do what I want it to, unless there's part of the implementation I'm missing.
Here's my simple method:
- (IBAction)firstNameNext:(id)sender {
[firstNameTextField resignFirstResponder];
[surnameTextField becomeFirstResponder];
}
Any advice would be super.
Add UIScrollView in your main view then all contents as subview to UIScrollView
Now when specific UITextField needs to be able to visible in view use its delegate like this:
Note: add UITextFieldDelegate in .h file like this
#interface yourViewController : UIViewController<UITextFieldDelegate>
Also bind with File's Owner
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField;
{
if(textField == yourSpecficTextField) //one u want move upwards
{
yourScrollView.contentOffset = CGPointMake(0,200); //required offset
}
... //provide contentOffSet those who needed
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
yourScrollView.contentOffset = CGPointMake(0,0); //make UIScrollView as it was before
}
If you have keyboard input fields that will be covered by the virtual keyboard, then you need to move those fields out from under the virtual keyboard.
The normal way to do this is to have the controller's view be a scrollable view like UIScrollView. Moving Content That Is Located Under the Keyboard gives a very robust way of adjusting your scroll view and ensuring the required field shows.

Handling 'Done' button on the keyboard outside of textViewDidEndEditing

When "Done" is pressed I know textViewDidEndEditing: is called. It is also sometimes called by other actions.
I want a method that is only called when "Done" is pressed -- exclusively. I've been reading around for snippets of code, but don't see anybody doing this. I am not using any XIB for my view, by the way.
Is this possible?
An instance of UITextField will send a textFieldShouldReturn: message to its delegate whenever the Return key is pressed. If you want your controller to receive this message, have it send a setDelegate: message to the text field, passing self as the argument (or connect the text field's delegate outlet to the controller in Interface Builder) and implement the following method in your controller class:
- (BOOL)textFieldShouldReturn:(UITextField *)textField;
See the documentation for the UITextFieldDelegate protocol for further information.
Firstly, the textFieldDidEndEditing is called not when the user taps the DONE button. It is called as soon as you touch anything after editing.
For having an exclusive button 'Done' you can create a Done key as a UIBarButtonItem, and write an IBAction like
- (IBAction) doneClicked:(id)sender
The following line assigns the Done key as the Return Key.
textField.returnKeyType = UIReturnKeyDone;
You can check if the Done key was pressed in the TextFieldDidEndEditing...You may also use another button, and return it instead.

Why is it that my UITableViewController setEditing:animated: method is not called?

I must be doing stupid, but I can't see what: my UITableViewController subclass is never called when the edit button of my navigation is pressed.
What could be causing that?
My view hierarchy is loaded from a Nib file and put inside a popover. The [+] button is connected to the insertNewObject action of my UITableViewController subclass. It works fine.
The [Edit] button however has no action to connect to. The doc says it will automatically call the setEditing:animated: method of the view controller, which I override.
The nib file is set up pretty much as usual AFAICT. And in fact, I'm not sure what additional detail I can give that would suggest my mistake.
What is the control flow from the click on the [Edit] button to the call of the setEditing:animated method?
I feel like we must be missing the same thing.
Whatever the case, I made it work by doing the following.
IBOutlet UIBarButtonItem *editButton;
-(IBAction)editButtonPressed:(id)sender {
[self setEditing:YES animated:YES];
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animate
{
if(self.tableView.isEditing)
{
self.editButton.style = UIBarButtonItemStylePlain;
self.editButton.title = #"Edit";
}
else
{
//self.editButton.style = UIBarButtonSystemItemDone;
self.editButton.style = UIBarButtonSystemItemEdit;
self.editButton.title = #"Done";
}
// Toggle table view state
[super setEditing:!self.tableView.isEditing animated:animate];
}
I hooked the editButton up to the button I added to the nav bar and it's action to the editButtonPressed IBAction. After doing that my setEditing: is called (obviously) and the super call toggles the table view's editing state.
I'd like to use the system defined button styles, but the appropriate one is commented out because while it did change style I couldn't figure out how to change the text from "Edit" to "Done" so I had to do it all manually (that only worked if I left the button as Custom and set the style generically). This has the downside of not being localized (for free), etc.