I am new in iOS and I am facing problem regarding to create Custom delegate of UITextField
My code is like this
In CustomTableView
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
if([self.delegate respondsToSelector:#selector(textFieldShouldEndEditing:)])
{
[self.delegate textFieldShouldEndEditing:textField];
}
return YES;
}
In View Controller
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
return YES;
}
But this method is not getting call in ViewController.
Can Any body please tell me what I am doing wrong
Thanks in Advance!
You should not call textField's delegates methods manually like [self.delegate textFieldShouldEndEditing:textField];
If you want to call your delegate method from another class then make some method which is not provided by sdk!
for example make method like,
- (BOOL)myTextFieldShouldEndEditing:(UITextField *)textField
{
return YES;
}
and call this method from your other class by your self.delegate and make sure that self.delegate is not nil, i mean it have object of your viewController!
you need to create a custom TextField class and also set delegate in that class. Like this
.h File
#interface CustomTextField : UITextField<UITextFieldDelegate>
#end
.m File
#implementation CustomTextField
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.delegate = self;
}
return self;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField{
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField{
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
return YES;
}
- (BOOL)textFieldShouldClear:(UITextField *)textField{
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
return YES;
}
#end
Related
I want the keyboard to disappear when the user presses the "return" button, but I have tried resignFirstResponder, endEditing:YES and -
(BOOL)disablesAutomaticKeyboardDismissal {return NO;}and the keyboard still didn't disappear. What should I do?
Here's the relevant code: (everything else is empty (viewDidLoad is empty, etc.)
#implementation ViewController {
__weak IBOutlet UITextField *textfield;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textfield resignFirstResponder];
//[self.view endEditing:YES]; (I uncommented this out and tested it)
return YES;
}
- (BOOL)disablesAutomaticKeyboardDismissal {
return NO;
}
plz confirm your UITextField Delegate From Storyboard or set
textfield.delegate = self;
in - (void)viewDidLoad
and use the methode
-(BOOL) textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
I have outlet the connection of UITextField and written this code
-(void)viewDidLoad
{
[txtName addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
}
-(void)textFieldDidChange :(UITextField *)theTextField{
NSLog(#"Text changed");
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if(textField==txtName)
{
[self.view endEditing:YES];
[self performSelector:#selector(ShowNames) withObject:nil afterDelay:0.1];
return NO;
}
return YES;
}
But -(void)textFieldDidChange :(UITextField *)theTextField{ is not fired
Couldn't understand where Am I going wrong
Any help would be appreciated
Replace the code method
-(void)textFieldDidChange :(UITextField *)theTextField{
NSLog(#"Text changed");
}
with
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
If you want to UITextField events you should use UITextFieldDelegate
In your .h file adopt UITextFieldDelegate
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITextFieldDelegate>
and then in your .m file
- (void)viewDidLoad
{
[super viewDidLoad];
[_txtName setDelegate:self];
}
Let me know if you have any issues
You've got the right idea, but your problem is within your -(BOOL)textFieldShouldBeginEditing:(UITextField *)textField method.
Right now, before editing this method is called, and if the method returns NO, then the -(void)textFieldDidChange :(UITextField *)theTextField method will not be called.
Your if statement tests to see if the textField that should start editing is the same as txtName. If it does you are returning NO instead of YES. I think you just need to swap your NO's and YES's and you'll be golden.
Try this:
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if(textField==txtName)
{
[self.view endEditing:YES];
[self performSelector:#selector(ShowNames) withObject:nil afterDelay:0.1];
return YES;
}
return NO;
}
so I've been trying to get this pickerview working but I just can't get it to work. When I run the app it crashes without any stacktrace and shows Thread 1: EXC_BAD_ACCESS on [textField becomeFirstResponder]. The pickerArray is correct, so that's not the problem.
#import "TestViewController.h"
#import "FindClasses.h"
#interface TestViewController ()
#property UIPickerView *picker;
#property NSArray *pickerArray;
#property (nonatomic, strong) FindClasses *finder;
#end
#implementation TestViewController
#synthesize finder = _finder;
- (FindClasses *)finder
{
if (!_finder) _finder = [[FindClasses alloc] init];
return _finder;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.pickerArray = [self.finder findClassesInTimetable];
self.classField.delegate = self;
self.picker = [[UIPickerView alloc] init];
self.picker.delegate = self;
self.picker.dataSource = self;
self.classField.inputView = self.picker;
// Do any additional setup after loading the view.
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
[textField becomeFirstResponder];
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
return YES;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UIPickerView method implementation
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return self.pickerArray.count;
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
return [self.pickerArray objectAtIndex:row];
}
Thanks.
Try removing [textField becomeFirstResponder]; from the following method:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
[textField becomeFirstResponder];
return YES;
}
The error is not relating to the picker field. The becomeFirstResponder is called automatically when the text field is selected. So there is no need for it to be called here as it would have already been called when you clicked the text field.
Basically your telling the text field that is active, to become active... Give it a go and let me know what the result is.
In relation to the picker view not showing up, make sure you have the IBOutlets connected up properly if using storyboards, also edit the following at the top of you .m file so it looks like the below:
Before:
#interface TestViewController ()
After:
#interface TestViewController () <UIPickerViewDataSource, UIPickerViewDataSource>
to have ur pickerview as your first responder, use
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if([textField isEqual:classField]) {
[textField setInputView:picker]; //edited ones
[picker becomeFirstResponder];
}
}
use this method,
it will help you.
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
if ([self.classField isEditing]) {
[self.picker selectRow:0 inComponent:0 animated:YES]; //This is not necessary but I prefer it for my purpose
[self.picker reloadAllComponents];
}
}
And Make sure your TextField Delegate is calling ... Means <UITextFieldDelegate> must be in your .h file like <UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource>
Hope This Helps You...
If this doesn't work then Try this
self.picker = [[UIPickerView alloc]initWithFrame:CGRectZero];
[self.picker setDataSource:self];
[self.picker setDelegate:self];
[self.classField setInputView:self.picker]
I'd like to create a text field which uses the number pad and accepts only numbers, even when pasted. Currently, I have a header as such:
#import <UIKit/UIKit.h>
#interface DRPNumberTextField : UITextField <UITextFieldDelegate>
#end
and an implementation:
#import "DRPNumberTextField.h"
#implementation DRPNumberTextField
- (id) initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
self.delegate = self;
[self setKeyboardType:UIKeyboardTypeNumberPad];
}
return self;
}
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if ([string rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location != NSNotFound)
{
return NO;
}
return YES;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
I've set the text fields to use this class in the storyboard. However, my desired functionality does not occur. Moreover, as determined by debugging, initWithFrame: is never called. Any ideas? As more context, these text fields are embedded inside table cells of a table view of a table view controller. Of these, I provide a custom implementation of the table view controller here:
#interface DRPImplementSettingsViewController ()
#end
#implementation DRPImplementSettingsViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
Thus it really has no implemented functionality beyond the stock. Its header is the obvious one.
EDIT: As some have pointed out, I don't need to subclass the text field to implement delegate functionality. I can put that elsewhere. But my question is this: why doesn't what I've presented here work? I can't find my mistake.
You need also override - (id)initWithCoder:(NSCoder *)decoder in your DRPNumberTextField. if you are using the custom UITextField in XIB or storyboard, initWithFrame: will not be called, initWithCoder: is called instead.
You can try with this also,
Its also works
DRPNumberTextField.m
#import "DRPNumberTextField.h"
#implementation DRPNumberTextField
- (void)awakeFromNib
{
[super awakeFromNib];
self.delegate = self;
[self setKeyboardType:UIKeyboardTypeNumberPad];
}
- (BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if ([string rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location != NSNotFound)
{
return NO;
}
return YES;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
You don't need to subclass to do this, you can just implement theUITextFieldDelegate method textField:shouldChangeCharactersInRange:replacementString:. Every time the method is called check that the replacementString only contains characters you want to allow and return YES or NO depending on whether it does.
Here is an alternative to subclassing, rather subclassing you can use delegate method of textfield for that
check this,
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
#define NUMBERS #"0123456789"
#define NUMBERSPERIOD #"0123456789-"
NSCharacterSet *cs;
NSString *filtered;
// Period is in use
if (textField.tag==8)
{
cs = [[NSCharacterSet characterSetWithCharactersInString:NUMBERS] invertedSet];
filtered = [[string componentsSeparatedByCharactersInSet:cs] componentsJoinedByString:#""];
return [string isEqualToString:filtered];
}
return YES;
}
Set your textfield tag appropriate . It will also want past other character.
I have two fields, fldPassword and fldUsername. With this code (and a self delegate in the view did load), I would expect the return key to dismiss at both of the text fields. However, it only does it on the first. What am I doing wrong?
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
if (fldPassword == self->fldPassword) {
[fldPassword resignFirstResponder];
} else if (fldUsername == self->fldUsername) {
[self->fldUsername becomeFirstResponder];
}
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
[theTextField resignFirstResponder];
return YES;
}
in your .h file add delegate method :
#interface YourViewController : UIViewController<UITextFieldDelegate>
then it will work for both textfields.
hope this helps u.
You are dismissing only the fist one, try this:
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
if (fldPassword == self->fldPassword) {
[fldPassword resignFirstResponder];
}
if (fldUsername == self->fldUsername) {
[self->fldUsername resignFirstResponder];
}
return YES;
}