navigate through textfields - objective-c

I'm trying to use the #PeyloW code that I found here How to navigate through textfields (Next / Done Buttons) but when I press the keyboard return button nothing happens. My tags are ok.
Header:
- (BOOL)textFieldShouldReturn:(UITextField*)textField;
Implementation:
- (BOOL)textFieldShouldReturn:(UITextField*)textField {
NSInteger nextTag = textField.tag + 1;
UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];
if (nextResponder) {
[nextResponder becomeFirstResponder];
} else {
[textField resignFirstResponder];
}
return NO;
}
What am I missing? My keyboard doesn't have next done, only return. Keep in mind that I'm very new to iOS.
EDIT:
I tried to debug the code by adding a breakpoint to it and the code isn't being triggered.

I don't like solutions that incorporate the tag. Instead I would put all inputfileds in the desired order into an array and in -textFieldShouldReturn: use the given textfield to get it's index from in the array. Then I would get the object at that index.
- (BOOL)textFieldShouldReturn:(UITextField*)textField {
NSUInteger nextIndex = [arrayWithResponders indexOfObject:textField]+1 % [arrayWithResponders count];
UIResponder* nextResponder = [arrayWithTextFields objectAtIndex: nextIndex];
if (nextResponder) {
[nextResponder becomeFirstResponder];
} else {
[textField resignFirstResponder];
}
return NO;
}
You just added, that the breakpoints aren't triggered, so most likely you didn't set up the delegate.

Related

NSTextField nextKeyView is ignored

although i set the nextKeyView of the NSTextField, the focus is gained by a different NSTextField
tried "Auto Recalculates View Loop" checked / unchecked
toggled "Full Keyboard Access"
tried also catching the tab in
code
- (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector {
BOOL result = NO;
if (commandSelector == #selector(insertTab:)) {
// tab action:
result = NO;
}
return result;
}
There returning YES / No, tired to set the next responder as
[self.window makeFirstResponder:self.nextKeyView]
With no success
selecting the NSTextField with selectText:, while catching the 'Tab' worked (note you have to return YES, meaning you are are processing the Tab)... you cannot rely purely on the nextKeyView
Put this in your NSTextField subclass and link the nextKeyView
- (BOOL)control:(NSControl*)control textView:(NSTextView*)textView doCommandBySelector:(SEL)commandSelector
{
BOOL result = NO;
if (commandSelector == #selector(insertTab:)) {
// tab action:
// always insert a tab character and don’t cause the receiver to end editing
if ([self.nextKeyView isKindOfClass:[NSTextField class]]) {
[(NSTextField *)self.nextKeyView selectText:self];
result = YES;
} else {
//[textView insertTabIgnoringFieldEditor:self];
result = NO;
}
}
return result;
}

Disable long press menu in text area/input UIWebview

This seems to be one of the most frequently discussed topics here but I couldn't find a solution which actually works. I'm posting this question to share a solution which I found as well as hoping to find a better/cleaner solution
Description of situation:
There is a UIWebview in my application
There is text input/area in the webview
Long pressing on the text area/input brings up a context menu with 'cut', 'copy', 'define' etc.
We need to disable this menu without disabling user input.
What I've tried so far
(Stuff that doesn't work) :
Override canPerformAction
This solution tells us to add canPerformAction:withSender: to either subclass of UIWebview or in a delegate of UIWebview.
- (BOOL) canPerformAction:(SEL)action withSender:(id)sender
{
if (action == #selector(defineSelection:))
{
return NO;
}
else if (action == #selector(translateSelection:))
{
return NO;
}
else if (action == #selector(copy:))
{
return NO;
}
return [super canPerformAction:action withSender:sender];
}
Does not work because the canPerformAction: in this class is does not get called for menu items displayed.
Since the sharedMenuController interacts with the first responder in the Responder chain, implementing canPerformAction in the container skipped select and selectAll because they had already been handled by a child menu.
Manipulating CSS
Add the following to CSS:
html {
-webkit-user-select: none;
-webkit-touch-callout: none;
-webkit-tap-highlight-color:rgba(0,0,0,0);
}
This does work on images and hyperlinks but not on inputs.
:(
The root cause of the first solution not working is the subview called UIWebBrowserView. This seems to be the view whose canPerformAction returns true for any action displayed in the context menu.
Since this UIWebBrowserView is a private class we shouldn't try to subclass it (because it will get your app rejected).
So what we do instead is we make another method called mightPerformAction:withSender:, like so-
- (BOOL)mightPerformAction:(SEL)action withSender:(id)sender {
NSLog(#"******Action!! %#******",NSStringFromSelector(action));
if (action == #selector(copy:))
{
NSLog(#"Copy Selector");
return NO;
}
else if (action == #selector(cut:))
{
NSLog(#"cut Selector");
return NO;
}
else if (action == NSSelectorFromString(#"_define:"))
{
NSLog(#"define Selector");
return NO;
}
else if (action == #selector(paste:))
{
NSLog(#"paste Selector");
return NO;
}
else
{
return [super canPerformAction:action withSender:sender];
}
}
and add another method to replace canPerformAction:withSender: with mightPerformAction:withSender:
- (void) replaceUIWebBrowserView: (UIView *)view
{
//Iterate through subviews recursively looking for UIWebBrowserView
for (UIView *sub in view.subviews) {
[self replaceUIWebBrowserView:sub];
if ([NSStringFromClass([sub class]) isEqualToString:#"UIWebBrowserView"]) {
Class class = sub.class;
SEL originalSelector = #selector(canPerformAction:withSender:);
SEL swizzledSelector = #selector(mightPerformAction:withSender:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(self.class, swizzledSelector);
//add the method mightPerformAction:withSender: to UIWebBrowserView
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
//replace canPerformAction:withSender: with mightPerformAction:withSender:
if (didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
}
}
And finally call it in the viewDidLoad of the ViewController:
[self replaceUIWebBrowserView:self.webView];
Note: Add #import <objc/runtime.h> to your viewController then error(Method) will not shown.
Note: I am using NSSelectorFromString method to avoid detection of private API selectors during the review process.
Also you can hide menu:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(menuWillBeShown:) name:UIMenuControllerWillShowMenuNotification object:nil];
...
- (void)menuWillBeShown:(NSNotification *)notification {
dispatch_async(dispatch_get_main_queue(),^{
[[UIMenuController sharedMenuController] setMenuVisible:NO animated:NO];
});
}
The essential trick here is dispatch_async.

textBox is not firstResponder even though it is the only textBox I have picked

As soon as I run the program, I select the first textBox and then select a second textBox. fNameDone runs when textBox 1 touchUpOutside.The NSLogs are there to check if the textbox is the first responder and both nslogs return false. But it is the only textBox I have picked. My ultimate goal is to have each text box I pick, the keyboard goes away when I touchUpOutside.
- (IBAction)fNameDone:(id)sender
{
if([_firstName isEditing])
NSLog(#"True");
else
NSLog(#"False");
[self.view endEditing:TRUE];
if([_firstName isEditing])
NSLog(#"True");
else
NSLog(#"False");
}
Try this (there is no textbox in iOS I think you mean TextField)
- (BOOL)textFieldShouldReturn:(UITextField*)aTextField
{
if(aTextField.tag == 100){
[pickerView setHidden:YES];
return NO;
}
[aTextField resignFirstResponder];
return YES;
}
Don't forgot to set the delegate of textfield
EDIT:
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if(aTextField.tag == 100){
firstField.inputVIew = pickerView ;
}
}

Is Empty selection in an NSTableView with Source List Highlighting not allowed?

I feel like I may be missing something obvious here, but if I have an NSTableView with it's Highlight set to Source List and with Empty selection enabled, I don't seem to be able to click on a blank row in the table to clear the selection.
Changing the Highlight to regular fixes the problem, but of course doesn't draw in the manner I'd like.
The table has no bindings and uses a custom data source. Is there a way to work around this limitation?
For now, I've ended up adding the following to my NSTableView subclass:
- (void)mouseDown:(NSEvent *)theEvent
{
[super mouseDown:theEvent];
if ( [self allowsEmptySelection] && [self selectionHighlightStyle] == NSTableViewSelectionHighlightStyleSourceList )
{
NSInteger row = [self rowAtPoint:[self convertPoint:[theEvent locationInWindow] fromView:nil]];
if ( row == -1 )
{
[self deselectAll:nil];
}
}
}
You can use target actions to accomplish this. During initialization do the following:
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.target = self;
self.tableView.action = #selector(singleClickAction:);
self.tableView.allowsEmptySelection = YES;
Then add a method to your class:
- (void)singleClickAction:(id)sender
{
NSInteger clickedRow = [sender clickedRow];
if (clickedRow < 0) {
[self.tableView deselectAll:self];
}
}

How do I get a UITextField to accept focus without showing the keyboard?

I am trying to find a way to prevent the keyboard from appearing when the user taps on a TextField but could`t find a way to do it.
I tried this code after I linked my textField to delegate and still it did not work for me, the code was logging but the keyboard did appear.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
NSLog(#"BeginEditing");
return YES;
[textField resignFirstResponder];
}
When I return with NO I lose the focus from the textField, which I need.
The textFields I have are filled with values from a buttons on the same view, thats why I don't want the keyboard to appear, and at the same time I want the user to select the textField they want to fill.
if you just want user to select the textfield to fill and does not want to keyboard to show up then you can do the following:
add tag to your textfields
change the code to this:
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
selectedTextFieldTag = textField.tag;
return NO;
}
use selectedTextField value to identify which textfield to fill in your code. return NO will not allow keyboard to appear.
This will help you for sure.
-(BOOL)textFieldShouldBeginEditing:(UITextField*)textField {
UIView *dummyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
activeField.inputView = dummyView; // Hide keyboard, but show blinking cursor
return YES;
}
I tested and it is working for me. Hope this will be useful for others who have similar issue.
[textField resignFirstResponder]; will not be called because you are returning from the method before it can get called. Does that not fire a warning?
Try returning NO here or if that doesn't work, try disabling user-interaction on the text field:
[myTextField setUserInteractionEnabled:NO];
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
NSLog(#"BeginEditing");
[textField resignFirstResponder];
return YES;
}
so here you just use flag int variable to assign the value to focused textfield
define int i; flag globally in .h or .m file
after that in textField Delegate method use bellow code...
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if (textField == yourtextField1 ) {
i=1;
}
else if (textField == yourtextField2 ) {
i=2;
}
else if (textField == yourtextField3 ) {
i=3;
}
else if (textField == yourtextField4 ) {
i=4;
}
return NO;
}
-(IBAction)yourbutton1_Clicked:(id)sender{
if( i == 1){
yourtextField1.text=yourbutton1.titleLabel.text;
}
else if ( i == 2){
yourtextField2.text=yourbutton1.titleLabel.text;
}
else if ( i == 3){
yourtextField3.text=yourbutton1.titleLabel.text;
}
else if ( i == 4){
yourtextField4.text=yourbutton1.titleLabel.text;
}
else{
NSLog(#"Please Click On TextField");//here you can put AlertView Message
}
}
and so on.......
also you can use common method with sender id of button and also tag......