Handling 'Done' button on the keyboard outside of textViewDidEndEditing - objective-c

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.

Related

Detect enter key pressed from custom NSTextView completion list

I'm trying to detect the enter key from a custom NSTextView (from a NSTextField completion list) but I can't get it to work.
My interface:
#interface PaddedTextView : NSTextView < NSTextViewDelegate >
I implement:
- (BOOL)textView:(NSTextView *)textView doCommandBySelector (SEL)commandSelector
{
But it is never called.
The Completion list disappears when I press enter after selecting an option.
I have also implemented:
- (void)keyDown:(NSEvent *)event
and it will detect alpha numeric key events but not the enter key.
I also have implemented flagsChanged to capture the shift key and that works.
I am using a custom NSTextField, NSTextFieldCell and NSTextView.
When I select a completion entry and hit the enter key the value will be inserted into the NSTextField control but I want to perform an action when this happens and I can't detect it...
Any help is appreciated.
Thanks
I found a solution to my problem. (Update: This doesn't work)
I added the following to my NSTextView implementation:
-(void) insertCompletion:(NSString *)word forPartialWordRange:(NSRange)charRange movement:(NSInteger)movement isFinal:(BOOL)flag {
if(movement == NSReturnTextMovement){
NSLog(#"Enter key pressed...");
}
[super insertCompletion:word forPartialWordRange:charRange movement:movement isFinal:flag];
}
Update: Actually this doesn't always work. This function is only called when a completion option is selected. If you type in the text field and hit enter I can't detect that key event, it only dismisses the completion list. Still looking for a real solution.
I'm not sure about the completion list implementation, However at least on a normal NSTextView, insertNewline:(id)sender will be invoked when enter key is pressed.

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

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.

Objective-C difference between resolving events and actions

Im new to Objective-C & iOS programming so Im very confused about event and action handling. I don't really understand what is the difference between connecting a button in Interface builder with its files owner method (for instance connecting button action pressed with my personal method buttonClicked) and on the other hand creating a delegate which will respond to button events? I am confused because I come from C# (.NET) and there you only handling events via delegation.
Let's create event handling programmatically first. Some assumptions ...
you have class MyViewController
this class does contain property myButton (UIButton *)
you do want to handle events in this class
First step is to create method to handle your button taps:
-(void)onMyButtonTap:(UIButton *)sender {
// My button was tapped, whoa, which one is in sender argument
}
Add tap event handling:
-(void)loadView {
[super loadView];
[self.myButton addTarget:self action:#selector(onMyButtonTap:) forControlEvents: UIControlEventTouchUpInside];
}
What this code does? self in this case is instance of MyViewController class, which is going to handle touch up inside event (addTarget). action is method which will be called when UIControlEventTouchUpInside fires.
So the addTarget:... line adds event handling and when the control event fires, this ...
[self onMyButtonTap:self.myButton];
... will be called automatically.
It's simplified example, it can be more complicated in the real world:
you can have UIButton in separate UIView (good practice, I dislike when people put them in UIViewController)
you can handle multiple buttons taps in one method (distinguish between them by sender argument)
you can create more tap handling methods, one method for one button,
...
And now back to outlets. Outlet is just an automatic glue for addTarget:....
UIButton is subclass of UIControl and here you can see how other events can be handled and what events you can handle.
Delegation is also common practice, but not for UIControl. There's no delegate, etc. You have to do it in this way.
Or you can enhance UIButton to handle events via blocks for example. Here's one way https://gist.github.com/2468899 or you can Google for more.

Hide keyboard when hitting return key in IOS5

I have tried this solution to hide keyboard but it doesn't work...
How to hide the keyboard when i press return key in a UITextField?
Many thanks
assuming you are using UITextField, how do you create the textfield? is it by xib? or by code? make sure you implement UITextFieldDelegate in your class
#interface YouClass : UIViewController <UITextFieldDelegate>
if its xib, connect your textField to the file owner's delegate. and also connect your File owner to your IBOutlet UITextField
if its by code. just do
yourTextField.delegate = self;
now implement
-(BOOL)textFieldShouldReturn:(UITextField *)textField
Just resign as first responder in your input text field, when the return key pressed. The keyboard will dismissed automatically.
You need to set the Return button to actual built in function type. In one of my apps I have set it as a "Done" button because when the user has finished they can press this and it will drop the keyboard away. To set this add this to your code in somewhere like the -(void)viewDidLoad; method.
textFieldName.returnKeyType = UIReturnKeyDone;
That should then give you a blue done button on the keyboard that hides it.

UIPageControl value changed not firing

I have an issue with the UIPageControl. I simplified the issue for clarity below:
I put a button and a UIPageControl in my app with Interface builder and put the following in the code:
- (IBAction)tappedButton:(id)sender{
self.pageControl.currentPage = 3;
NSLog(#"Tapped Button");
}
- (IBAction)changePage:(id)sender{
NSLog(#"PAGE Changed!!!!");
}
I attached the Value Changed action to the pageController via Interface Builder.
When I tap on the button, I see the output "Tapped Button" and the third dot is highlighted... but the changePage method is never called.
Any ideas?
The changePage: method will only be called when the users request a change of page using the UIPageControl. It won't be called when the user taps the button. If you want to call the changePage: method when the button is pressed called it explicitly:
[self changePage: nil];
UIPageControl doesn't actually change pages for you. You have to write that code, inresponse to the valueChanged event. So, you want to connect that event of your UIPageControl object to your output (tappedButton: I guess), and then call your changePage: method to actually change the UI. Does that help?
There are some example projects referenced from the Apple docs that use UIScrollView and UIPageControl together. Check 'em out.