-textFieldShouldBeginEditing is invoked for all textFields rather than when each textField is selected - uitextfield

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.

Related

How to display sheet view in NSWindow

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.

Not being able to edit NSTextField on NSPopover even though Editable behavior is set

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

Keypad in iphone is not going?

In my application, whenever i tap a textfield the keypad will be visible, i have used the
[textField resignFirstResponder];
to that textfield's IBOutlet, but still the return key in keypad is not enabled, so cannot make the keypad go away.It enables only after i type some Characters in the textfield.
First make sure you had set the "delegate" of your textfield in Interface Builder. You can set it by dragging its "delegate" attribute link to the File's Owner.
Here titleFld is the name of my UITextField.
Setting delegate of your textfield will enable your compiler to call your "textfield delegate methods".
you can also do this programmatic by
[yourTextFieldName setDelegate: self];
//Set "self" if you have its delegates method in the same file.
If you want to move out your keyboard from the screen on its "return" key press then below code will do this task.
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return NO;
}
But make sure you set the delegate of your textfield...
I like keeping a button on the top-left of my "editable" views that resembles the iPad icon of "hide keyboard". This way, the user can always hides the keyboard when needed.
Also, if your UITextField is not editable, the keyboard will not show.
By default the return key in UITextField is not enabled until the user has typed some text. You can change this behavior so that the return key is always enabled by setting enablesReturnKeyAutomatically, either programatically with the UITextInputTraits protocol or in Xcode IB.

resignFirstResponder not hiding keyboard on textFieldShouldReturn

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
}

How to disable drag-n-drop for NSTextField?

I want to disallow dropping anything into my NSTextField. In my app, users can drag and drop iCal events into a different part of the GUI. Now I've had a test user who accidentally dropped the iCal event into the text field – but he didn't realize this because the text is inserted in the lines above the one that I see in my one-line text field.
(You can reveal the inserted text by clicking into the text field and using the keyboard to go one line up – but a normal user wouldn't do this because he/she wouldn't even have realized that something got inserted in the first place!)
I tried registerForDraggedTypes:[NSArray array]] (doesn't seem to have any effect) as well as implementing the draggingEntered: delegate method returning NSDragOperationNone (the delegate method isn't even invoked).
Any ideas?
EDIT: Of course dropping something onto an NSTextField only works when it has focus, as described by ssp in his blog and in the comments to a blog entry by Daniel Jalkut.
I am glad you discovered the comments in my blog post. I think they are the tip of the iceberg to discovering how to achieve what you're looking for.
You need to keep in mind that the reason dragging to an NSTextField works when it has focus, is that the NSTextField has itself been temporarily obscured by a richer, more powerful view (an NSTextView), which is called the "Field Editor."
Check out this section of Apple's documentation on the field editor:
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/TextEditing/Tasks/FieldEditor.html
To achieve what you're striving for, I think you might need to intercept the standard provision of the field editor for your NSTextFields, by implementing the window delegate method:
windowWillReturnFieldEditor:toObject:
This gives you the opportunity to either tweak the configuration on the NSTextView, or provide a completely new field editor object.
In the worst case scenario, you could provide your own NSTextView subclass as the field editor, which was designed to reject all drags.
This might work: If you subclass NSTextView and implement -acceptableDragTypes to return nil, then the text view will be disabled as a drag destination. I also had to implement the NSDraggingDestination methods -draggingEntered: and -draggingUpdated: to return NSDragOperationNone.
#implementation NoDragTextView
- (NSArray *)acceptableDragTypes
{
return nil;
}
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender
{
return NSDragOperationNone;
}
- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender
{
return NSDragOperationNone;
}
#end
I was able to solve this problem by creating a custom NSTextView and implementing the enter and exit NSDraggingDestination protocol methods to set the NSTextView to hidden. Once the text field is hidden the superview will be able to catch the drag/drop events, or if the superview doesn't implement or want the drag/drop they are discarded
For example:
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender {
//hide so that the drop event falls through into superview's drag/drop view
[self setHidden:YES];
return NSDragOperationNone;
}
- (void)draggingExited:(id<NSDraggingInfo>)sender {
//show our field editor again since dragging is all over with
[self setHidden:NO];
}
Have you tried - (void)unregisterDraggedTypes from NSView?

Resources