UITextField clearButtonMode and UIPicker - iphone

I have an extended UITextField (added a NSString property, inputType to it) to take in user input. when the user tap's the text field, i use a picker for the user to select the input. i also need to allow the user to clear the text box so i thought i could use
tillageTextField.clearButtonMode = UITextFieldViewModeAlways;
to clear the text field.
the issue is when you tap the X to clear the text box, it also fires my picker. i use:
-(BOOL) textFieldShouldBeginEditing:(MyTextField *) textField
{
//other code
else if ([textField.inputType isEqualToString:#"tillageMethod"])
{
self.customArray = [NSArray arrayWithObjects:#"No Till", #"Strip Till", #"Full Till", nil];
self.tempTextField = textField;
[self showPicker];
return NO;
}
//other code
}
to show the picker.
is there a way for me to tell if the user tapped the clear button and not show the picker?

You could also implement textFieldShouldClear: and set a flag on your class (e.g. doNotShowPickerOnNextCallback)
- (BOOL)textFieldShouldClear:(UITextField *)textField {
if ([textField.inputType isEqualToString:#"tillageMethod"]) {
if (![self pickerIsShowing]) {
self.doNotShowPickerOnNextCallback = YES;
}
}
return YES;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
//other code
else if ([textField.inputType isEqualToString:#"tillageMethod"]) {
if (self.doNotShowPickerOnNextCallback) {
self.doNotShowPickerOnNextCallback = NO;
return NO;
}
self.customArray = [NSArray arrayWithObjects:#"No Till", #"Strip Till", #"Full Till", nil];
self.tempTextField = textField;
[self showPicker];
return NO;
}
}

Related

Enable Search button when searching string is empty in default search bar

In my application I am using search functionality using default IOS search bar, If i place some string for search its working fine but after the first search i need to display the entire data Source (original content) My functionality is if the search string is empty it will display the entire data source. My issue is if i make the search string as empty in default search bar, the search button automatically come to hide state. I need to enable the search button even the string is empty.
Actually you can just set searchBar.enablesReturnKeyAutomatically = NO; Tested on iOS 7+
This code display Search Button if you have empty string.
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
[self.searchBar setShowsCancelButton:YES animated:YES];
self.tblView.allowsSelection = NO;
self.tblView.scrollEnabled = NO;
UITextField *searchBarTextField = nil;
for (UIView *subview in self.searchBar.subviews)
{
if ([subview isKindOfClass:[UITextField class]])
{
searchBarTextField = (UITextField *)subview;
break;
}
}
searchBarTextField.enablesReturnKeyAutomatically = NO;
}
Swift 3/ iOS 10
for view1 in searchBar.subviews {
for view2 in view1.subviews {
if let searchBarTextField = view2 as? UITextField {
searchBarTextField.enablesReturnKeyAutomatically = false
break
}
}
}
Use the following code for enable return key with no text
UITextField *searchField = nil;
for (UIView *subview in searchBar.subviews) {
if ([subview isKindOfClass:[UITextField class]]) {
searchField = (UITextField *)subview;
break;
}
}
if (searchField) {
searchField.enablesReturnKeyAutomatically = NO;
}
Maybe is an apple side bug?. Since from the .xib file setting auto-enable return Key does not work as expected.
Just add the following code:
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
searchBar.enablesReturnKeyAutomatically = NO;
return YES;
}
Create a custom view & on that view add one button to remove the keyboard. Add that view when - (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar delegate method of UISearchBar.
On that button click resign the keyboard as well as the view which you created for that button. Also if you want to search on that button click then you can do it as well.
Please see image for more clarification.
Its almost same as the accepted answer but if You are working with iOS 7 you will need extra for loop due to some changes in search bar
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
[self.searchBar setShowsCancelButton:YES animated:YES];
UITextField *searchBarTextField = nil;
for (UIView *mainview in self.searchBar.subviews)
{
for (UIView *subview in mainview.subviews) {
if ([subview isKindOfClass:[UITextField class]])
{
searchBarTextField = (UITextField *)subview;
break;
}
}
}
searchBarTextField.enablesReturnKeyAutomatically = NO;
}
Use this it works for ios 6 and 7:
- (void)searchBarTextDidBeginEditing:(UISearchBar *)search
{
UITextField *searchBarTextField = nil;
for (UIView *mainview in search.subviews) {
if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {
if ([mainview isKindOfClass:[UITextField class]]) {
searchBarTextField = (UITextField *)mainview;
break;
}
}
for (UIView *subview in mainview.subviews) {
if ([subview isKindOfClass:[UITextField class]]) {
searchBarTextField = (UITextField *)subview;
break;
}
}
}
searchBarTextField.enablesReturnKeyAutomatically = NO;
}
If you're looking for a bit more elegant solution, you could use recursion to find the textfield within the searchbar, as shown below. This should work for ios 6, 7, or any other future ios barring any deprecations by apple.
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
UITextField* textField = [self findTextFieldInView:searchBar];
if (textField) {
textField.enablesReturnKeyAutomatically = NO;
}
}
-(UITextField*)findTextFieldInView:(UIView*)view {
if ([view isKindOfClass:[UITextField class]]) {
return (UITextField*)view;
}
for (UIView* subview in view.subviews) {
UITextField* textField = [self findTextFieldInView:subview];
if (textField) {
return textField;
}
}
return nil;
}
Simple Swift version:
if let searchTextField:UITextField = searchBar.subviews[0].subviews[2] as? UITextField {
searchTextField.enablesReturnKeyAutomatically = false
}
Here is a solution using Swift. Just paste it in your viewDidLoad function and make sure that you have an IBOutlet of your searchBar in the code. (on my example below, the inputSearchBar variable is the IBOutlet)
// making the search button available when the search text is empty
var searchBarTextField : UITextField!
for view1 in inputSearchBar.subviews {
for view2 in view1.subviews {
if view2.isKindOfClass(UITextField) {
searchBarTextField = view2 as UITextField
searchBarTextField.enablesReturnKeyAutomatically = false
break
}
}
}
In swift use UISearchBarDelegate
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
searchBar.enablesReturnKeyAutomatically = false
}`

text field is not getting clear

I have a textfield from which I show a popover for textfield value string.
When I edit the text field the clear button is visible, however, when I click the clear button,
textfield text doesn't disappear but the popover is dismissed.
How can I fix this please?
Below is code fragment
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if ([popOverController isPopoverVisible])
{
[popOverController dismissPopoverAnimated:YES];
}
if(textField.tag == SERVER_TAG){
if ([[self getServerList] count]) {
[self createPopUp];
}
} else {
[serverNameTf resignFirstResponder];
}
}
- (BOOL)textFieldShouldClear:(UITextField *)textField {
return YES;
}
Its better if you paste your code that you tried.
But as i understood from your question, you may not set the TEXTFIELDs delegate,
so st the textfields delegate to self.
ie. textfield.delegate = self
and also make changes as >>
[textField setText:#""];
[popOverController dismissPopoverAnimated:YES];
Try this out.
if ([popOverController isPopoverVisible])
{
[textField setText:#""];
[popOverController dismissPopoverAnimated:YES];
}

Hide UIMenuController in UITextView

Subclassed UITextView
Here is h file
#interface CTextView : UITextView {
}
#end
Here is m file code
#import "CTextView.h"
#implementation CTextView
- (BOOL)canBecameFirstResponder {
return NO;
}
#end
Here is first UIViewController file in which subclassed UITextview is using
#import "First.h"
#import "CTextView.h"
textView = [[[CTextView alloc] initWithFrame:CGRectMake(0, 0, 320, 410)]autorelease];
[self.view addSubview:textView];
But still not able to prevent copy select all from UITextView. Please let me know if i am still missing anything or doing wrong.
Thanks for help.
Use this to disable copy:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
return NO;
}
Got it. Now it is working
Here is the code for reference for anyone need it
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
[UIMenuController sharedMenuController].menuVisible = NO; //do not display the menu
if (action == #selector(copy:))
{
return NO;
}
else if (action == #selector(selectAll:))
{
return NO;
}
[self resignFirstResponder]; //do not allow the user to selected anything
return NO;
return [super canPerformAction:action withSender:sender];
}
Now only problem having is Zooming. Now i have to work on that to disable it from UITextView.
Have you set the user interaction enabled to YES?

Dynamic UIMenuItems with #selector and dynamic methods

I am trying to use UIMenuController for a dynamical menu (titles and actions come from a server). The problem is that I have to use UIMenuItems initWithTitle:action: where action is a #selector.
I can use #selector(dispatch:) but then I am not able to distinguish which of the items the user pressed. - (void)dispatch:(id)sender { NSLog(#"%#", sender); } says it is a UIMenuController and It don't have a method which would tell which menu item was pressed.
I can't just write 100 methods to dispatch every possible selector, ok there will not be more then 10 but still, this seems not a good idea.
Do I have to create dynamic methods for each such selector? http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtDynamicResolution.html? This seems odd too.
Any better propositions then this two?
// This approach doesn't work.
- (void)showMenu {
[self becomeFirstResponder];
NSMutableArray *menuItems = [[NSMutableArray alloc] init];
UIMenuItem *item;
for (MLAction *action in self.dataSource.actions) {
item = [[UIMenuItem alloc] initWithTitle:action.title action:#selector(action:)];
[menuItems addObject:item];
[item release];
}
UIMenuController *menuController = [UIMenuController sharedMenuController];
menuController.menuItems = menuItems;
[menuItems release];
[menuController update];
[menuController setMenuVisible:YES animated:YES];
}
- (void)action:(id)sender {
NSLog(#"%#", sender); // gives UIMenuController instead of UIMenuItem
// I can not know which menu item was pressed
}
// This approach is really ugly.
- (void)showMenu {
[self becomeFirstResponder];
NSMutableArray *menuItems = [[NSMutableArray alloc] initWithCapacity:5];
UIMenuItem *item;
NSInteger i = 0;
for (MLAction *action in self.dataSource.actions) {
item = [[UIMenuItem alloc] initWithTitle:action.text
action:NSSelectorFromString([NSString stringWithFormat:#"action%i:", i++])];
[menuItems addObject:item];
[item release];
}
UIMenuController *menuController = [UIMenuController sharedMenuController];
menuController.menuItems = menuItems;
[menuItems release];
[menuController update];
[menuController setMenuVisible:YES animated:YES];
}
- (void)action:(NSInteger)number {
NSLog(#"%i", number); // gives the index of the action in the menu.
}
// This is a hack, I have to assume that there will never be more then 15 actions
- (void)action0:(id)sender { [self action:0]; }
- (void)action1:(id)sender { [self action:1]; }
- (void)action2:(id)sender { [self action:2]; }
- (void)action3:(id)sender { [self action:3]; }
- (void)action4:(id)sender { [self action:4]; }
- (void)action5:(id)sender { [self action:5]; }
- (void)action6:(id)sender { [self action:6]; }
- (void)action7:(id)sender { [self action:7]; }
- (void)action8:(id)sender { [self action:8]; }
- (void)action9:(id)sender { [self action:8]; }
- (void)action10:(id)sender { [self action:10]; }
- (void)action11:(id)sender { [self action:11]; }
- (void)action12:(id)sender { [self action:12]; }
- (void)action13:(id)sender { [self action:13]; }
- (void)action14:(id)sender { [self action:14]; }
That approach would work, although you need a unique selector-name for every button and a mapping from that name to whatever you want to target.
For the selector name a unique string has to be chosen (UUIDs or maybe a sanitized & prefixed version of the title would work). Then you need one method that resolves the call and "alias" it with the different selector names:
- (void)updateMenu:(NSArray *)menuEntries {
Class cls = [self class];
SEL fwd = #selector(forwarder:);
for (MenuEntry *entry in menuEntries) {
SEL sel = [self uniqueActionSelector];
// assuming keys not being retained, otherwise use NSValue:
[self.actionDict addObject:entry.url forKey:sel];
class_addMethod(cls, sel, [cls instanceMethodForSelector:fwd], "v#:#");
// now add menu item with sel as the action
}
}
Now the forwarder can look up what URL is associated with the menu item:
- (void)forwarder:(UIMenuController *)mc {
NSLog(#"URL for item is: %#", [actionDict objectForKey:_cmd]);
}
To generate the selectors you could use something like:
- (SEL)uniqueActionSelector {
NSString *unique = ...; // the unique part
NSString *selString = [NSString stringWithFormat:#"menu_%#:", unique];
SEL sel = sel_registerName([selString UTF8String]);
return sel;
}
Unless the menu items do the same thing, why should they share an action? I would go ahead and write actions that specify a behavior you want and link the menu items up to those.

Disable text selection UITextView

I want to disable text selection on a UITextView. Until now what i've
already done is:
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
[UIMenuController sharedMenuController].menuVisible = NO;
if (action == #selector(paste:))
return NO;
if (action == #selector(select:))
return NO;
if (action == #selector(selectAll:))
return NO;
return NO;
}
In this away I set UIMenuController to hidden and i put a stop to text copy but the text selection is still visible.
Google results (also StackOverflow) take me to no solution. Has someone already faced the
same problem? Any ideas?
If you want to prevent the text selection but keep links interactions, add the following textview delegate methods
- (void)textViewDidChangeSelection:(UITextView *)textView
{
[textView setSelectedRange:NSMakeRange(NSNotFound, 0)];
}
If you want to disable cut/copy/paste on all UITextView of your application you can use a category with :
#implementation UITextView (DisableCopyPaste)
- (BOOL)canBecomeFirstResponder
{
return NO;
}
#end
It saves a subclassing... :-)
Otherwise, just subclass UITextViewand put :
- (BOOL)canBecomeFirstResponder
{
return NO;
}
textView.editable = NO;
or
[textView setEnabled:NO];
im not sure what u meant