I have a view with a UITextField which should hide the keyboard when return is pressed.
My function is this:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if ( textField == userPassword ) {
[textField resignFirstResponder];
}
return YES;
}
Normally the keyboard should be hidden but it stays on the screen. resignFirstResponder is correctly called. What am I missing?
I see you have the iPad tag on this. Do you happen to be presenting a modal view using UIModalPresentationFormSheet? If so, it looks like this is a limitation of the FormSheet modal presentation (either Apple is doing it intentionally for some reason, or it is a bug). See these other questions for more details:
Modal Dialog Does Not Dismiss Keyboard
Modal View Controller with keyboard on landscape iPad changes location when dismissed
There is this helpful method which allows you to dismiss the keyboard when presenting the Modal Dialog:
- (BOOL)disablesAutomaticKeyboardDismissal { return NO; }
This will override the default behavior of the modal dialog set by Apple and allow you dismiss the keyboard. It is in the UIViewController Class.
I hope this helps someone!
If you are using the Interface Builder, look if your UITextField has the delegated linked with your class.
-Select your UITextField and in your Connections look if exits one connection in Outlets->delegate. If not, conect with you File's Owner Class.
This need to be linked with your File's Owner Class. This delegate tell where to search for a method. If your are overriding a method, you need to tell where the object will search for that.
This solution worked for me after none of the above did. after calling resignFirstResponder i added a modal view & removed it.
[myTextField resignFirstResponder];
UIViewController *dummyController = [[UIViewController alloc] init];
UIView *dummy = [[UIView alloc] initWithFrame:CGRectMake(-1, -1,1,1)];
[dummyController setView:dummy];
[self presentModalViewController:dummyController animated:NO];
[dummyController dismissModalViewControllerAnimated:NO];
To deal with the bug mentioned by Brandon, you can try closing and re-opening your modal view controller as long as you still have a reference to it.
[textField resignFirstResponder];
[self dismissModalViewControllerAnimated:NO];
[self presentModalViewController:yourModalViewControllerReference animated:NO];
(where "self" should be the controller you used to originally open the modal view controller)
I was having the same problem. I realized that after connecting the delegate to the File's Owner in Interface Builder, I neglected to save in Interface Builder. Once I saved, I recompiled and the keyboard disappears correctly when hitting return.
xcode 4.5.1
Simply click control then on the textfield drag and release on the .h file
(control key+ drag)
then in the pop up menu select
connection=acton;
name= any name;
type=id;
event=did end on exit;
arguments=sender;
then click connect button
Did you remember to implement the UITextFieldDelegate protocol?
I have read so many articles about this issue, where the onscreen keyboard refuses to hide when you call resignFirstResponder, but none of the suggestions worked for me.
I'm using XCode 5 (iOS 7) and have a iPhone screen containing a couple of controls which require the onscreen keyboard, but if the user clicks on the UIButton, then I want the keyboard to disappear.
I probably wasted one full day experimenting with resignFirstResponder and adding disablesAutomaticKeyboardDismissal functions to return NO, but nothing worked. Once the onscreen keyboard appeared, I could never get it to disappear again.
But then I had a small brainwave (as I only have a small brain).
Now, when the user clicks on my UIButton, I simply disable the UITextField and UITextView controls.
- (IBAction)btnDate_Tapped:(id)sender {
// The user has clicked on the "Date" button.
self.tbClientName.enabled = NO;
self.tbComments.editable = NO;
And suddenly, the app finds it has no editable text fields needing an onscreen keyboard, and it neatly slides the keyboard out of sight.
(Relieved sigh.)
My UIButton actually makes a popup dialog appear. When the user dismisses the popup, I re-enable these two controls, so if the user taps in one of them, the keyboard will appear again.
-(void)popoverControllerDidDismissPopover:(UIPopoverController *) popoverController {
// The user has closed our popup dialog.
// We need to make our UITextField and UITextView editable again.
self.tbClientName.enabled = YES;
self.tbComments.editable = YES;
... etc...
}
Simple, isn't it !
And surprisingly, this workaround even works on UIViewControllers which appear in Modal style.
I hope this helps other XCode victims out there.
Based on your comment that it looks like focus has shifted, then I think what may be happening is that the keyboard is staying open for the next text input field. If your return key is a "Next" key, then returning YES for textFieldShouldReturn: will make the next textField the first responder, and keep the keyboard visible.
The easiest way is:
Go to your user interface builder,
select UITextField and "Control-Drag" to "Detail View Controller-Detail" and release.
The window will pop-up. Then under "Outlets" select "Delegate".
That's it. It worked for me.
if you are in UIModalPresentationFormSheet just call
- (BOOL)disablesAutomaticKeyboardDismissal
{
return NO;
}
Swift 3.0:
override var disablesAutomaticKeyboardDismissal: Bool {
get{
return false
}
set {
self.disablesAutomaticKeyboardDismissal = false
}
}
Swift 3.0
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
if textField == addressTextField {
textField.resignFirstResponder()
return false
}
return true
}
Related
I have an iPad app (XCode 6.1, iOS 8.1.1, ARC and Storyboards). In one of the classes (scene) I have this code:
-(BOOL) textFieldShouldBeginEditing:(UITextField *)textField { // (prevents keyboard from showing)
if(textField.tag == 200) { // birthdate
[self showModalCalendar:(int)textField.tag];
return NO; // don't show k/b
}
else
return YES;
}
It is executed when the first textField is selected, going through each textField rather than wait until each textField is selected. This is a problem because what I want to accomplish is to show the modal calendar only when a particular UITextField (birthdate) has been selected, and NOT show the keyboard. What's happening is when I tap the tab key (on a hard keyboard) the modal calendar also apprears for each textField.
Is there any way to prevent this?
The problem in my case was IQKeyboardManager library. I removed this library from my project and DownPicker works fine.
Rather than using tags you should create an IBOutlet to the particular textView that you want to handle. Then you can test if textView == your special one in the delegate callback.
The reason is that it is more explicit and clearer than using tags. My guess is that some of your other text views have that same tag for some reason and so your conditional isn't behaving as you think it should.
How do I implement the view in following image.
The view which appears when + button is clicked in System Preferences > Network
I have following questions:
Does this view system has a specific name (like popover), because I have seen it in many places in Mac.
How to implement it in IB ?
Can this be done in a popover window instead of NSWindow ?(or is it only possible in NSWindow like toolbar)
Update:
Updating the title for better visibility
In Cocoa these are called sheets. Take a look at the sheet programming guide, however, this is terribly out of date!
You need to call -beginSheet:completionHandler: on the window you want to display the sheet. If you have single-window application you can ask the AppDelegate for the window and launch the sheet like so,
// This code should be in AppDelegate which implement the -window method
NSWindow *targetWindow = [self window]; // the window to which you want to attach the sheet
NSWindow *sheetWindow = self.sheetWindowController.window // the window you want to display at a sheet
// Now start-up the sheet
[targetWindow beginSheet:sheetWindow completionHandler:^(NSModalResponse returnCode) {
switch (returnCode) {
case NSModalResponseCancel:
NSLog(#"%#", #"NSModalResponseCancel");
break;
case NSModalResponseOK:
NSLog(#"%#", #"NSModalResponseOK");
break;
default:
break;
}
}];
You will notice that when the sheet completes it will return a certain modal response --- we will return to this point in a shortly.
Next you need to implement the content that you want to display in the sheet; this must be done in an NSWindow. I find it much easier to use a NSWindowController and implement the window in a separate XIB file. For example, see below,
Now you need to implement the code in your custom NSWindowController (or plain NSWindow if you are old-school and love to manage your own NIB loading) which will issue the correct modal response. Here I have hooked up the cancel and OK buttons to the following actions methods,
- (IBAction)cancelButtonAction:(id)sender {
[[[self window] sheetParent] endSheet:self.window returnCode:NSModalResponseCancel];
}
- (IBAction)OKButtonAction:(id)sender {
[[[self window] sheetParent] endSheet:self.window returnCode:NSModalResponseOK];
}
The model response will get sent to your completion handler block.
Sample project on github.
A NSStatusItem has a NSMenu attached, and one of the buttons of the NSMenu opens a NSWindow. Whenever one of these buttons is clicked, the window opens as expected and works properly, but another display of the NSStatusItem is opened.
The NSStatusItem is a clock, so I can see that it is updating correctly. However, the cloned NSStatusItem doesn't have its own menu. If I push the button that makes the window more times, more cloned versions of the NSStatusItem pop up.
Everything works fine except for this.
That's not a whole lot of information to go off of, but there's nothing else I can think of that could potentially help you. I would be happy to provide more information or try something.
EDIT: Every time the button is clicked, awakeFromNib is somehow called, which is why another half-working NSStatusItem happens.
EDIT: Temporary workaround is to put the awakeFromNib method in a dispatch_once.
EDIT: Added method that is triggered when button is clicked, as suggested by #zpasternack
- (IBAction)preferences:(id)sender {
self.windowController = [[NSWindowController alloc] initWithWindowNibName:#"PreferencesWindow"];
[[self windowController] showWindow:self];
}
Is the NSStatusItem contained in the PreferencesWindow nib? That might explain it, since you're loading the nib each time the button is clicked.
Also, is there a reason you need to recreate that window each time the button is clicked? Maybe you could only do it the first time?
- (IBAction)preferences:(id)sender {
if( self.windowController == nil ) {
self.windowController = [[NSWindowController alloc] initWithWindowNibName:#"PreferencesWindow"];
}
[[self windowController] showWindow:self];
}
I'm very new with iOS Development and I have just created one of my first apps, in my .xib file I have a UINavigationBar that I want to hide/show when a part of the screen is tapped by the user (like in the Photo app). I've found some snippets online but I don't know where and how to use those.
I'd appreciate a lot if somebody could give me detailed informations about how to do this.
Add this toggle method anywhere in your UIViewController. This hides on first tap and shows again in second tap.
- (void)toggleNavBar:(UITapGestureRecognizer *)gesture {
BOOL barsHidden = self.navigationController.navigationBar.hidden;
[self.navigationController setNavigationBarHidden:!barsHidden animated:YES];
}
If there is no navigation controller, link the navigation bar with an IBOutlet and replace with
- (void)toggleNavBar:(UITapGestureRecognizer *)gesture {
BOOL barsHidden = self.navBar.hidden;
self.navBar.hidden = !barsHidden;
}
Then add the following in the method -(void)viewDidLoad {}
UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(toggleNavBar:)];
[self.view addGestureRecognizer:gesture];
[gesture release];
If the view where you are going to tap is a UIWebViewController, you have to add the protocol to the view controller and set it as delegate gesture.delegate = self; then add the following:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
This is needed because the UIWebViewController already implements its own gesture recognizers.
Ultimately, you want to send the -setHidden: message to your navigation bar. The easiest way to do this is to make an Outlet and an Action in your in your view controller. Then, in your .xib file, connect the navigation bar to the outlet and some button (even a large, full screen one) to the action.
Outlets and Actions are basic techniques used over and over in iOS
(and Mac) programming, so if you don't understand them, best go read
up on them now. Every beginning iOS/Mac programming book covers this
topic as does Apple's own Getting Started guide (pay particular
attention to the Configuring the View section).
Inside your action, send a message to the outlet like so:
-(void)myButtonAction:(id)sender{
[[self myNavigationBarOutlet] setHidden:YES];
}
This will hide the navigation bar whenever your button is tapped.
(This assumes you have a UINavigationBar in your .xib like you say. These directions will be different if you're working with a UINavigationController that manages its own UINavigationBar)
I have an application, which open popover with NSTextField. The text field is not editable. Behavior for text field is set to Editable. I still can paste and copy text to this field but i can't edit it.
Anyone knows, what can be wrong?
Not sure if you still need the answer, but there may be some others still looking. I found a solution on apple developer forums. Quoting the original author:
The main problem is the way keyboard events works. Although the NSTextField (and all its superviews) receives keyboard events, it doesn't make any action. That happens because the view where the popover is atached, is in a window which can't become a key window. You can't access that window in any way, at least I couldn't. So the solution is override the method canBecomeKeyWindow for every NSWindow in our application using a category.
NSWindow+canBecomeKeyWindow.h
#interface NSWindow (canBecomeKeyWindow)
#end
NSWindow+canBecomeKeyWindow.m
#implementation NSWindow (canBecomeKeyWindow)
//This is to fix a bug with 10.7 where an NSPopover with a text field cannot be edited if its parent window won't become key
//The pragma statements disable the corresponding warning for overriding an already-implemented method
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
- (BOOL)canBecomeKeyWindow
{
return YES;
}
#pragma clang diagnostic pop
#end
That makes the popover fully resposive. If you need another window which must respond NO to canBecomeKeyWindow, you can always make a subclass.
I struggled with this for a while as well, until I realized it was a bug.
However, instead of relying on an isActive state of a NSStatusItem view, I find it much more reliable to use the isShown property of the NSPopover you have implemented.
In my code, I have a NSPopover in a NSViewController:
- (BOOL)canBecomeKeyWindow
{
if([self class]==NSClassFromString(#"NSStatusBarWindow"))
{
NSPopover *mainPopover = [[((AppDelegate*)[NSApp delegate]) mainViewController] mainPopover];
if(![mainPopover isShown])
return NO;
}
return YES;
}
Balazs Toth's answer works, but if you're attaching the popover to NSStatusItem.view the status item becomes unresponsive - requiring two clicks to focus.
What i found when working with this solution is that when NSStatusItem becomes unresponsive, you can easily override this behavior like this
- (BOOL)canBecomeKeyWindow {
if([self class]==NSClassFromString(#"NSStatusBarWindow")) {
CBStatusBarView* view = [((CBAppDelegate*)[NSApp delegate]) statusItemView];
if(![view isActive]) return NO;
}
return YES;
}
You will check for the class of the window, if it matches the NSStatusBarWindow we can then check somehow if the NSStatusItem is active. If it is, that means we have to return YES, because this way the NSPopover from NSStatusItem will have all keyboard events.
What I'm using for checking if the NSStatusItem was clicked (or is active) is that in my own custom view i have a bool value which changes when user clicks on the NSStatusItem, system automatically checks for "canBecomeKeyWindow" and when it does it will return NO and after user clicks on it (while it is returning the NO) it will change the bool value and return YES when system asks again (when NSPopover is being clicked for NSTextField editing).
Sidenotes:
CBStatusBarView is my custom view for NSStatusItem
CBAppDelegate is my App Delegate class
If anyone is still looking for an answer to this, I am working in Swift.
At the time where you wish the field to allow text entry, I have used myTextField.becomeFirstReponder()
To opt out; just use myTextField.resignFirstResponder()
Definitely a bug. That bug report is exactly what I was trying to do. Even down to creating the status item and overriding mousdown.
I can confirm that Balazs Toth's answer works. I just wonder if it might get in the way down the road.
If someone gets it and the solution above didn't do the trick for him.
The problem in my app was in the info tab in the targets my application was set to
Application is background only = true
and shulde of been
Application is agent = true
Spent an entire day on this thing.
Bug. http://openradar.appspot.com/9722231