Which count max char in UITextField and UITextView - objective-c

Which count maximum char's in UITextField and UITextView? It is really interesting for me! I have some textfields and textviews. And if I don't set max value for it, then which count char's can be in it?

You need to implement UITextFieldDelegate and UITextViewDelegate Method to get the count of characters
Try this code
For UITextView's
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
NSUInteger enteredTextLength; // Variable to store the length on entered string.
if(textView == txtViewName) {
enteredTextLength = [textView.text length] + [text length] - range.length;
NSLog(#"Text Length = %d", enteredTextLength);
// To check number of characters entered.
if (enteredTextLength < 10) {
return YES;
}
else {
return NO;
}
}
else {
return YES;
}
}
For UITextField's
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSUInteger enteredTextLength; // Variable to store the length on entered string.
if(textField == txtAlpha) {
enteredTextLength = [textField.text length] + [string length] - range.length;
NSLog(#"Text Length = %d", enteredTextLength);
// To check number of characters entered.
if (enteredTextLength < 10) {
return YES;
}
else {
return NO;
}
}
else {
return YES;
}
}

Related

NSRangeException when I have multiple pickerViews for multiple textfields

#import "ProfileViewController.h"
#implementation ProfileViewController{
NSArray *currentArray;
UITextField *currentTextField;
}
#synthesize picker, Feets, Inchs, Weights, Months, Days, Years, HeightValue, WeightValue, DOBValue;
#synthesize scrollView;
int variabla;
// Control the textfield go up when tap the textfield and keyboard coming out
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGPoint scrollPoint = CGPointMake(0, textField.frame.origin.y);
[scrollView setContentOffset:scrollPoint animated:YES];
[textField resignFirstResponder];
[picker setHidden:YES];
currentTextField = textField;
NSLog(#"222222");
if (currentTextField == HeightValue)
{
NSLog(#"3333333");
[HeightValue resignFirstResponder];
[picker setHidden:NO];
variabla = 1;
}
else if (currentTextField == WeightValue)
{
NSLog(#"4444444");
[WeightValue resignFirstResponder];
[picker setHidden:NO];
variabla = 2;
}
else if (currentTextField == DOBValue){
NSLog(#"5555555");
[DOBValue resignFirstResponder];
[picker setHidden:NO];
variabla = 3;
}
NSLog(#"variabla %d",variabla);
[picker reloadAllComponents];
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"111111");
NSString *path = [[NSBundle mainBundle]pathForResource:#"WeightList" ofType:#"plist"];
Weights = [[NSMutableArray alloc]initWithContentsOfFile:path];
[picker setHidden:YES];
Feets = [[NSMutableArray alloc]initWithObjects:#"0ft", #"1ft", #"2ft", #"3ft", #"4ft", #"5ft", #"6ft", #"7ft", #"8ft", #"9ft",nil];
Inchs = [[NSMutableArray alloc]initWithObjects:#"0in", #"1in", #"2in", #"3in", #"4in", #"5in", #"6in", #"7in", #"8in", #"9in", #"10in", #"11in",nil];
Months = [[NSMutableArray alloc]initWithObjects:#"1", #"2", #"3",nil];
Days = [[NSMutableArray alloc]initWithObjects:#"1", #"2", #"3",nil];
Years = [[NSMutableArray alloc]initWithObjects:#"1", #"2", #"3",nil];
#pragma mark - UIPcikerView DataSource and Delegate method
// returns the number of 'columns' to display.
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
if (variabla == 1){
return 2;
}
else if (variabla == 2){
return 1;
}
else
return 3;
}
// returns the # of rows in each component..
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
if (variabla == 1){
if (component == feetComponent)
return [Feets count];
if (component == inchComponent)
return [Inchs count];
}
if (variabla == 2){
return [Weights count];
}
else{
if (component == monthComponent)
return [Months count];
if (component == dayComponent)
return [Days count];
else
return [Years count];
}
}
// set the row text to the textfield
- (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component __TVOS_PROHIBITED{
if (variabla == 1){
if (component == feetComponent)
return Feets[row];
if (component == inchComponent)
return Inchs[row];
}
if (variabla == 2){
return Weights[row];
}
else{
if (component == monthComponent)
return Months[row];
if (component == dayComponent)
return Days[row];
else
return Years[row];
}
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component __TVOS_PROHIBITED{
if (currentTextField == HeightValue){
NSInteger feetRow = [picker selectedRowInComponent:feetComponent];
NSInteger inchRow = [picker selectedRowInComponent:inchComponent];
NSString *feet = Feets[feetRow];
NSString *inch = Inchs[inchRow];
NSString *msg = [[NSString alloc]initWithFormat:#"%# %#", feet, inch];
HeightValue.text = msg;
}
if (currentTextField == WeightValue){
NSInteger weightRow = [picker selectedRowInComponent:weightComponent];
NSString *weight = Weights[weightRow];
NSString *msg2 = [[NSString alloc]initWithFormat:#"%#",weight];
WeightValue.text = msg2;
}
if (currentTextField == DOBValue){
NSInteger monthRow = [picker selectedRowInComponent:monthComponent];
NSInteger dayRow = [picker selectedRowInComponent:dayComponent];
NSInteger yearRow = [picker selectedRowInComponent:yearComponent];
NSString *month = Months[monthRow];
NSString *day = Days[dayRow];
NSString *year = Years[yearRow];
NSString *msg3 = [[NSString alloc]initWithFormat:#"%# / %# / %#", month, day, year];
WeightValue.text = msg3;
}
}
#end
Above is the .m file code. When I run the simulator, the first textfield for the Height is working fine, but in the Weight and Date textfield, the picker view got the exception.
Simulator screen shot
NSRangeException screen shot
Well the exception says Index 5 beyond bounds [0..0]. So that says you have an array of size 1 but are asking it for the object at index 5, which doesn't make sense, so it crashes.
The traceback says that objectAtIndex method is being called from selectedRowInComponent:, which is being called from your didSelectRow:inComponent. So that suggests that you're passing an invalid component number to selectedRowInComponent.
I don't know where weightComponent and month/day/yearComponent are being set, but I'm guessing that they are not being set to 0 and 0, 1, and 2 respectively.
As an aside, I would also add that when you have a picker with labels 0ft, 1ft etc, that you don't keep around all these tables. Instead of creating a table and indexing it, just answer the titleForRow call with return [NSString stringWithFormat:#"%dft",row];

Moving the cursor once max length is reached

I've crudely put together this code based on some other answers on SO but I still can't get it to work. I want my cursor to move to the next textField once a certain length has been reached, and it does that...to an extent.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField.tag == 0 && range.location >= 1) {
[_secondTextField becomeFirstResponder];
return YES;
} else if (textField.tag == 1 && range.location >= 2) {
[_thirdTextField becomeFirstResponder];
return YES;
} else if (textField.tag == 2 && range.location >= 1) {
[_fourthTextField becomeFirstResponder];
return YES;
} else {
return YES;
}
}
...
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
// catched the delegates for the input textfields
_firstTextField.delegate = self;
_secondTextField.delegate = self;
_thirdTextField.delegate = self;
[_firstTextField becomeFirstResponder];
}
So I have 4 textfields, and I have character limits of 1, 2, and 1 for the first 3 text fields. The problem right now is the cursor will not move to the next textfield until after I type more text. This next text is in the new textfield, so the overall effect is achieved, but the cursor just isn't moving at the right time.
What can I do so that the cursor will move as soon as I reach the character limit?
A better way would be to use the didChange method like the UITextViewDelegate method, but as we know the UITextFieldDelegate does not have a didChange method. You can manually add behaviour. You can use the shouldChangeCharactersInRange: method, but personally I would advise not to override methods unless you absolutely have to.
You can add behaviour using:
[yourTextField addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
And in the target method:
- (void)textFieldDidChange:(UITextField*)textField{
if (textField.tag == 0 && textField.text.length == 1){
[_secondTextField becomeFirstResponder];
}else if (textField.tag == 1 && textField.text.length == 2){
[_thirdTextField becomeFirstResponder];
}else if (textField.tag == 2 && textField.text.length == 1){
[_fourthTextField becomeFirstResponder];
}
}

Date and time masking with text field

Hello everyone,
I am working on a project where requirement is keypad should not pop up when we clicked on the text field as we are making number pad for the particular text field and we have succeed for doing this by..
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
if (textField == dateFld) {
UIView* dummyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
textField.inputView = dummyView;
}
}
Now my problem is, I want to validate that text field to accept only particular format and limited number of input but i am unable to do this because the method for that is not getting called when we disabled the keypad to pop below is my code to validate the textfield.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
//Format Date of Birth YYYY-MM-DD
if(textField == dateFld)
{
if ((dateFld.text.length == 4)||(dateFld.text.length == 7))
//Handle backspace being pressed
if (![string isEqualToString:#""])
dateFld.text = [dateFld.text stringByAppendingString:#"-"];
return !([textField.text length]>9 && [string length] > range.length);
}
else
return YES;
}
Please help me to over come from this problem or any other way to do this.
Thanks
I want to validate that text field to accept only particular format and limited number of input :
if(textField == dateFld){
NSCharacterSet* numberCharSet = [NSCharacterSet characterSetWithCharactersInString:#"0123456789+"];
for (int i = 0; i < [string length]; ++i)
{
unichar c = [string characterAtIndex:i];
if (![numberCharSet characterIsMember:c])
{
return NO;
}
}
//Format Date of Birth YYYY-MM-DD
if([textField.text length] == 4) {
textField.text=[NSString stringWithFormat:#"%#-",textField.text];
}else if([textField.text length]==6){
textField.text=[NSString stringWithFormat:#"%#-",textField.text];
}else if([textField.text length]==8){
textField.text=[NSString stringWithFormat:#"%#",textField.text];
}
NSLog(#"value %#",textField.text);
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 13) ? NO : YES;
}
}
It's working fine for me.
I would do something like this:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
NSError *_error = nil;
NSRegularExpression *_regularExpression = [NSRegularExpression regularExpressionWithPattern:#"^\\d{0,4}-{0,1}$|^\\d{4}-{1}\\d{0,2}-{0,1}$|^\\d{4}-{1}\\d{2}-{1}\\d{0,2}$" options:NSRegularExpressionCaseInsensitive error:&_error];
NSMutableString *_newText = [NSMutableString stringWithString:textField.text];
[_newText insertString:string atIndex:range.location];
NSArray *_matches = [_regularExpression matchesInString:_newText options:0 range:NSMakeRange(0, _newText.length)];
return _matches.count > 0;
}
EDIT#1 (on 22/01/13)
of course, your class has to be a delegate class of your UITextField, otherwise the method above will be never called back.
there are some additional steps how you can do it.
in the YourViewController.h file:
#interface YourViewController : UIViewController <UITextFieldDelegate> {
// ...
}
#property (nonatomic, strong) IBOutlet UITextField *myTextField; // is case of ARC and iOS5+
#end
in your YourViewController.m file
- (void)viewDidLoad
{
[super viewDidLoad];
// ...
[self.myTextField setDelegate:self]; // you can do the same thing in the interface builder as well.
}
You need to validate the inputs in your dummyView
UIView* dummyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
textField.inputView = dummyView;
since you replaced the input view of UITextField, UITextField delegates will not be called.

UITextView "Field"

I would like a text similar to Twitter's
I am currently using a UITextView since it has multi-line support. I kind of figured out how to use a label that counts the characters and keeps the user up to date of any characters added or removed.
Empty:
With Text:
The problem I am having however is when I copy or paste any text in the view, (like if I highlight all the text, as in the second picture) and I delete it, the counter will not update. Or if I paste any text, the count just decrements one character, though the text field limit still stays correct, just the counter is no longer in sync with it.
Code: http://pastebin.com/UK91Ccbb
There is a delegate method for UITextView as
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
it is called every time a character is inserted into the UITextView. In this method set the length of text in your counter UILabel as follows
counterlabel.text = [NSString stringWithFormat:#"%i", textView.text.length];
return YES at the end of method if the length is within range i.e. less than or equal to 140 else return NO.
UPDATE:..
To restrict to 140 characters.
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
return textView.text.length <= 140;
}
To handle text removal on selection and counting characters.
- (void)textViewDidChange:(UITextView *)textView
{
count.text = [NSString stringWithFormat:#"%i", (140- textView.text.length)];
}
NSLog(#"You added a character");
charactersLeft--;
I think the problem here is that you should have written:
charactersLeft -= text.length;
In viewDidLoad :
charactersLeft = 140;
characterCountLabel.text = [NSString stringWithFormat:#"%d",charactersLeft];
Now use this it works well :
- (void)textViewDidChange:(UITextView *)textView{
NSString *textString = textView.text;
int chars = [textString length];
if (chars <= 140) {
[characterCountLabel setText:[NSString stringWithFormat:#"%d",(140 - chars)]];
}
}
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if([text isEqualToString:#"\n"])
[textView resignFirstResponder];
if (textView.text.length == 140 && [text isEqualToString:#"\n"]) {
[textView resignFirstResponder];
}
else if ((textView.text.length) >= 140 && range.length == 0){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"" message:#"You have exceeded the characters limit." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
return NO; // return NO to not change text
}
return YES;
}
Note that here I have used returnType key to resign the keyboard.You may change it to work as usual.

picker view shows numbers in pickerview but not showing properly on label?

i have added a pickerview from interface builder.i am using this method to show data like this....
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if (pickerView == SpotPickerView) // don't show selection for the custom picker
{
// report the selection to the UI label
label.text = [NSString stringWithFormat:#"%d - %# - %d",[pickerView selectedRowInComponent:0],
[RowArray objectAtIndex:[pickerView selectedRowInComponent:1]],
[pickerView selectedRowInComponent:2]];
}
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
NSString *returnStr = #"";
if (pickerView == SpotPickerView)
{
if (component == 0)
{
returnStr = [[NSNumber numberWithInt:row+1] stringValue];
}
else if(component==1)
{
returnStr = [RowArray objectAtIndex:row];
}
else
{
returnStr =[[NSNumber numberWithInt:row+1] stringValue];
}
}
return returnStr;
}
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
{
CGFloat componentWidth = 0.0;
if (component == 0)
componentWidth = 90.0;
else if (component == 1)
componentWidth = 100.0;
else
componentWidth = 90.0;
return componentWidth;
}
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
{
return 40.0;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
int count;
if (component == 0)
count = 15;
else if (component == 1)
count=[RowArray count];
else
count = 100;
return count;
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 3;
}
here is the RowArray
- (void)viewDidLoad {
RowArray = [[NSArray arrayWithObjects:
#"A", #"B", #"C",
#"D", #"E", #"F", #"G",#"H",#"I",#"J",#"K",#"L",#"M",#"N",#"O",#"P",#"Q",#"R",#"S",#"T",
#"U",#"V",#"W",#"X",#"Y",#"Z",
nil] retain];
}
but selecting the first row shows this.
i need to store the values in database so i need the 1 instead of zero.
also how do i reset my picker view.means when i click on a button it automatically comes to the 0th index in each column.
label.text = [NSString stringWithFormat:#"%d - %# - %d",[pickerView selectedRowInComponent:0],
[RowArray objectAtIndex:[pickerView selectedRowInComponent:1]],
[pickerView selectedRowInComponent:2]];
This code is retrieving the row number from the selected row in a component. Arrays are zero indexed and the pickerview (probably) uses array's to manage the rows. So, the first row will be 0, the second 1, the third 2 and so on. This is easily solved by doing:
[pickerView selectedRowInComponent:0] + 1
You can select certain rows programmatically by using selectRow:inComponent:animated If you want the select the 0th index in each column just do: [pickerView selectRow:0 inComponent:0 animated:YES] for every component.