Customized autocompletion in UITextView - iphone

I want to do the customized autocompletion for UITextView...
For example:
If the user starts to type "Busines" I would like to suggest "Business1", "Business2", , so that the user can select any one of the 2 suggestions or choose to type a new one.
All the custom word suggestion will be in the array...
How can I achieve this ??
Is completionsForPartialWordRange:inString:language: something that I can use.. How can I pass the values in the array???

You can try this code.
- (void)searchAutocompleteEntriesWithSubstring:(NSString *)substring
{
[autocomplete_array removeAllObjects];
for(int i=0;i<[your_main_array count];i++)
{
NSString *curString = [your_main_array objectAtIndex:i];
curString = [curString lowercaseString];
substring = [substring lowercaseString];
if ([curString rangeOfString:substring].location == NSNotFound)
{}
else
{
[autocomplete_array addObject:curString]
}
}
[autocompletedisplayTableView reloadData];
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if( textView == your_TextView)
{
[your_TextView resignFirstResponder];
autocompletedisplayTableView.hidden = NO;
NSString *substring = [NSString stringWithString:your_TextView.text];
substring = [substring stringByReplacingCharactersInRange:range withString:string];
[self searchAutocompleteEntriesWithSubstring:substring];
return YES;
}
}
your_main_array : will be your original array which you'll load from web service.
autocomplete_array : will be the array you'll get after the searching process is finished.
When user search you'll have to pass autocomplete_array to your UITableView

Related

I'm Trying to figure out the timing of the iOS Keyboard

So here is the situation of the timing. I have a UILabel that I want to update every time the keyboard updates a UITextField. I have two UITextFields but only one is ever the first responder so don't worry about there being two I have them for back end purposes. The problem is the timing from the UILabel updating and the UITextField delegate function
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string;˚
The replacement string doesn't get added until YES is returned to by the above function. I need to update my labels either after this function is called or during this function. I can't seem to figure out how it will work. The UILabel is always one character behind. Below is my code in general for this section.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if([self.hiddenTextFieldForTimeMinutes.text length] == 2 && [self.hiddenTextFieldForTime.text length] == 2 && ![string isEqualToString:#""])
{
return NO;
}
[self syncTextFieldsMinutesAndHours: string];
// This returns the default Yes;
return YES;
}
- (void) setAccessoryLabel: (NSString *) hourString minutesString: (NSString *) minuteString
{
timeAccessoryLabel.text = [NSString stringWithFormat:#"%#:%#", hourString, minuteString];
}
- (void) syncTextFieldsMinutesAndHours: (NSString *) string
{
// These are the textFields
NSMutableString *hoursString = [NSMutableString stringWithFormat: #"%#", self.hiddenTextFieldForTime.text];
NSMutableString *minutesString = [NSMutableString stringWithFormat: #"%#", self.hiddenTextFieldForTimeMinutes.text];
if([self.hiddenTextFieldForTimeMinutes.text length] == 2 && ![string isEqualToString: #""])
{
[hoursString appendString: [NSString stringWithFormat:#"%c", [minutesString characterAtIndex:0]]];
[self.hiddenTextFieldForTime setText:[NSString stringWithFormat:#"%#", hoursString]];
[self.hiddenTextFieldForTimeMinutes setText: [self.hiddenTextFieldForTimeMinutes.text substringFromIndex:1]];
} else if([self.hiddenTextFieldForTimeMinutes.text length] == 2 && [string isEqualToString: #""])
{
// Hours has nothing in it
if([hoursString length] == 0)
{
return;
} else if([hoursString length] == 1)
{
// Since the timing of the add and remove of the string is done by return of the delegate we append the string to the beginning first then return.
[self.hiddenTextFieldForTimeMinutes setText: [NSString stringWithFormat:#"%c%#", [self.hiddenTextFieldForTime.text characterAtIndex:0], self.hiddenTextFieldForTimeMinutes.text]];
[self.hiddenTextFieldForTime setText:#""];
} else if ([hoursString length] == 2)
{
// Since the timing of the add and remove of the string is done by return of the delegate we append the string to the beginning first then return.
[self.hiddenTextFieldForTimeMinutes setText: [NSString stringWithFormat:#"%c%#", [self.hiddenTextFieldForTime.text characterAtIndex:1], self.hiddenTextFieldForTimeMinutes.text]];
[self.hiddenTextFieldForTime setText: [NSString stringWithFormat:#"%c", [self.hiddenTextFieldForTime.text characterAtIndex:0]]];
}
}
[self setAccessoryLabel: self.hiddenTextFieldForTime.text minutesString:self.hiddenTextFieldForTimeMinutes.text];
}
yes. The text of the textField in textField:shouldChangeCharactersInRange:replacementString: will still have the old value, because it only gets changed after you answered yes to the question if the text should change.
You have two options.
create the NSString that your textField will have after you returned YES yourself:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if([self.hiddenTextFieldForTimeMinutes.text length] == 2 && [self.hiddenTextFieldForTime.text length] == 2 && ![string isEqualToString:#""])
{
return NO;
}
NSString *realString = [textField.text stringByReplacingCharactersInRange:range withString:string];
[self syncTextFieldsMinutesAndHours: realString];
// This returns the default Yes;
return YES;
}
or add a IBAction that gets called after the editing took place:
- (void)viewDidLoad {
// your viewDidLoad implementation
[textField addTarget:self action:#selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
}
- (IBAction)textFieldDidChange:(UITextField *)sender {
[self syncTextFieldsMinutesAndHours: sender.text];
}
After mulling for a few minutes, this could be a run loop issue. Try adding this before you call the method to update your UILabel:
[[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
//update label
[self updateLabelWithText:foo andText:bar];
Or try using GCD:
dispatch_queue_t main_queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
dispatch_async(main_queue, ^{
// UI Updates here
[self updateLabel...];
});
});

Searching the initial letter of a word using searchBar

In my app, i have a search bar in my contact list page tableview. now my code searches the list based on any letter even if the search text is at the middle of the firstname or lastname. But i want it to search only from the beginning. For example., the word "sh" should pull only "Shiva", "Sheela", etc., but not "sathish", "suresh" etc., can anyone help me on this?
and my code is
- (void)searchBar:(UISearchBar *)searchBar
textDidChange:(NSString *)searchText
{
//---if there is something to search for---
if ([searchText length] > 0)
{
isSearchOn = YES;
canSelectRow = YES;
self.ContactTableview.scrollEnabled = YES;
searchTextValue = searchText;
[searchResult removeAllObjects];
for (NSString *str in ContactArray)
{
NSRange range = [str rangeOfString:searchText options:NSCaseInsensitiveSearch];
if(range.location != NSNotFound)
{
if(range.length > 0)//that is we are checking only the start of the names.
{
[searchResult addObject:str];
}
}
}
}
else
{
//---nothing to search---
isSearchOn = NO;
canSelectRow = NO;
self.ContactTableview.scrollEnabled = YES;
//SearchBar.showsCancelButton = NO;
[TitleBarLabel setText:#"All Contacts"];
}
[ContactTableview reloadData];
}
try with predicates,in below code replace your values.
NSPredicate *p = [NSPredicate predicateWithFormat:#"SELF BEGINSWITH[cd] %#",#"A"];
NSArray *a = [NSArray arrayWithObjects:#"AhfjA ", #"test1", #"Test", #"AntA", nil];
NSArray *b = [a filteredArrayUsingPredicate:p];
NSLog(#"--%#",b);
O/P:-
(
AntA,
AntA
)

Backspace many characters in a row in a UITextView

I want to check if a user backspaces a character in a textView if there are any of that same character connecting it for it to delete them all...
For example if the character I'm checking for is "e" I have the text "easy heeeeeello" and the user starts hitting backspace it will become:
easy heeeeeello -> easy heeeeeell -> easy heeeeeel -> easy heeeeee -> easy h
The code should detect that a backspace was pressed.
Then it will detect which text is going to be deleted, and if that text is a character (in our case "e") it will check if there are more "e"s touching that "e" creating a strand of "e"s and delete them all.
Can you help me?
OK, so I wrote this code, and it works for me
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:#""]) {
//Detected backspace character as the new character is #"" meaning something will be deleted
char toDelete = [textView.text characterAtIndex:range.location];
int duplicateCharCount = 0;
for(int i =range.location-1; i>=0; i--) {
if([textView.text characterAtIndex:i] == toDelete) {
duplicateCharCount++;
} else {
break;
}
}
NSRange newRange = NSMakeRange(0, range.location - duplicateCharCount);
[textView setText:[textView.text substringWithRange:newRange]];
return NO;
} else {
return YES;
}
}
I know its not the best implementation, but now you know how to proceed
Hope this helps
Kind of fun, so I wrote the code just now.
The code works.
First, we should set the UITextView's delegate and respond to .
textView:shouldChangeTextInRange:replacementText:
According to the document,
If the user presses the Delete key, the length of the range is 1 and an empty string object replaces that single character.
So the code comes below :
#pragma mark -
#pragma mark - UITextView Delegate
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
static NSString *suffix = #"e";
if (range.length == 1 && [text length] == 0) {
// The user presses the Delete key.
NSString *currentText = [textView.text substringToIndex:range.location+1];
NSString *appendingText = [textView.text substringFromIndex:range.location+1];
if ([currentText hasSuffix:suffix]) {
NSRange range = [self inverseRangeOfString:currentText withSuffix:suffix];
currentText = [currentText stringByReplacingCharactersInRange:range withString:#""];
textView.text = [currentText stringByAppendingString:appendingText];
return NO;
}
}
return YES;
}
- (NSRange)inverseRangeOfString:(NSString *)str withSuffix:(NSString *)suffix
{
int length = [str length];
int lastIndex = length - 1;
int cnt = 0;
for (; lastIndex >= 0; --lastIndex) {
NSString *subStr = [str substringFromIndex:lastIndex];
if ([subStr hasPrefix:suffix]) {
cnt++;
} else {
break;
}
}
NSRange range = (NSRange){++lastIndex, cnt};
return range;
}

How to perform validation on textfield for phone number entered by user in iPhone?

I have an application where I have I a textfield where user enters his mobile number including his country code. The format of the mobile number to be entered is +91-9884715715. When the user enters his/her mobile number initially validation should be performed that the first value entered by user is '+' and then the number that is entered after + should not be less that 0.
But after this I am getting confused that how to get the number of numbers entered between + and -, because user enters the country code and the length of numbers entered between + and - must be dynamic not static.
Try this ., might help you
- (BOOL)textField:(UITextField *) textField shouldChangeCharactersInRange:(NSRange)range replacementString:
(NSString *)string {
NSString *newString = [textField.text stringByReplacingCharactersInRange:range withString:string];
if (textField == self.yourphoneNumberfield) {
NSArray *sep = [newString componentsSeparatedByString:#"-"];
if([sep count] >= 2)
{
countryCode = [NSString stringWithFormat:#"%#",[sep objectAtIndex:0]];
if ([[countryCode substringToIndex:1] isEqualToString:#"+"]) {
phoneNumber = [NSString stringWithFormat:#"%#",[sep objectAtIndex:1]];
return ([countryCode length]+[phoneNumber length]);
}
}
}
return YES;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{
NSLog(#"Phone Number : %#",phoneNumber);
if (textField == self.yourphoneNumberfield) {
if ([phoneNumber length]<10)
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"UIAlertView" message:#"Please Enter a Valid Mobile number" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
}
return YES;
}
Try This:
NSString *code=#"+91-99999999";
NSRange rr2 = [code rangeOfString:#"+"];
NSRange rr3 = [code rangeOfString:#"-"];
int lengt = rr3.location - rr2.location - rr2.length;
int location = rr2.location + rr2.length;
NSRange aa;
aa.location = location;
aa.length = lengt;
code = [code substringWithRange:aa];
NSLog(#"%#",code);
Goto XIB interface Builder and open xib document select ur phone number type textfield and go to textfield attribute, In the Text Input Traits, select Keyboard option from Default to Phone Pad.
// limit the input to only the stuff in this character set, so no emoji or any other insane characters
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:#"1234567890"];
if ([string rangeOfCharacterFromSet:set].location == NSNotFound) {
return NO;
}
Refer #Bala's answer
NSString *call = #"+91-9884715715";
// Search for the "+a" starting at the end of string
NSRange range = [call rangeOfString:#"+" options:NSBackwardsSearch];
// What did we find
if (range.length > 0)
NSLog(#"Range is: %#", NSStringFromRange(range));
Edit
Refer following link: TextField Validation With Regular Expression
Change the line
- (BOOL)validateInputWithString:(NSString *)aString
{
NSString * const regularExpression = #"^([+]{1})([0-9]{2,6})([-]{1})([0-9]{10})$";
NSError *error = NULL;
Add the code
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
char *x = (char*)[string UTF8String];
//NSLog(#"char index is %i",x[0]);
if([string isEqualToString:#"-"] || [string isEqualToString:#"+"] || [string isEqualToString:#"0"] || [string isEqualToString:#"1"] || [string isEqualToString:#"2"] || [string isEqualToString:#"3"] || [string isEqualToString:#"4"] || [string isEqualToString:#"5"] || [string isEqualToString:#"6"] || [string isEqualToString:#"7"] || [string isEqualToString:#"8"] || [string isEqualToString:#"9"] || x[0]==0 ) {
NSUInteger newLength = [textField.text length] + [string length] - range.length;
return (newLength > 18) ? NO : YES;
} else {
return NO;
}
}
Edit
Tested with demo:
//// Button Press Event
-(IBAction)Check:(id)sender{
BOOL check = [self validateInputWithString:TextField.text];
if(check == YES){
NSLog(#"Hii");
NSString *string= [NSString stringWithFormat:#"%#", TextField.text];
NSArray *first = [string componentsSeparatedByString:#"-"];
NSString *second = [first objectAtIndex:1];
NSString *third = [first objectAtIndex:0];
if([second length] < 11){
NSLog(#"bang");
}
else{
NSLog(#"Fault");
}
if([third length] > 3 || [third length] < 7){
NSLog(#"Bang");
}
else{
NSLog(#"fault");
}
}
else{
NSLog(#"FAULT");
}
}

UITextField restriction-iphone

I'm having 4 textfields in my application
1.username
2.Email
3.Age
4.Password
User names are 3-25 characters and contain only the characters [a-z0-9]
Age must be between 1-100 inclusive.
Passwords are between 4-12 characters and use only the characters [a-zA-Z0-9]
how can i restrict the textfield with above requirements
please anyone help me out to do this..
Thank you for your effort and consideration.
You can use the methods in the UITextFieldDelegate protocol to validate your fields' content.
More concretely, either you use:
– textFieldShouldEndEditing:
- textFieldShouldReturn:
or you can use:
- textField:shouldChangeCharactersInRange:replacementString:
In the first case, you only validate when the user ends editing the text field; in the second case, you can do the validation at each keystroke.
In all of those methods, you receive an argument textField which you can access like this:
NSString* text = textField.text;
NSUInterger length = [text length];
if (length.....) {
// -- show alert or whatever
return NO;
}
You can validate numbers as the user type by implementing -[UITextField textField:shouldChangeCharactersInRange:replacementString:] method. Do note that this method is called before the change is made, so you need to construct the text that could be the result of the users actions yourself. For example:
-(BOOL)textField:(UITextField*)textField: shouldChangeCharactersInRange:(NSRange*)range
replacementString:(NSString*)string;
{
NSString* text = [textField.text stringByReplacingCharactersInRange:range
withString:string];
// text is now the potential string you should check against.
}
What you do from there is up to your own. Some examples could be:
// Too short?
if ([text length] < 4) ...
// Invalid character?
NSCharacterSet* invalidChars = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
if ([text rangeOfCharacterInSet:invalidChars].location != NSNotFound) ...
For more complex number validation I would use NSNumberFormatter, that has support for validating ranges and more.
You can use UITextFieldDelegate to get done what you want. Assign different values to textfield.tag for each field in - (void)viewDidLoad method and match those tag values to find the relevant field in the (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string.
#define USERNAME_FIELD_TAG 1
#define PASSWORD_FIELD_TAG 2
#define EMAIL_FIELD_TAG 3
#define AGE_FIELD_TAG 4
#pragma mark - UITextFieldDelegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField.tab == USERNAME_FIELD_TAG)
{
if([[NSPredicate predicateWithFormat:#"SELF MATCHES[cd] %#", #"[a-z0-9]{3,35}"] evaluateWithObject:string] == FALSE)
{
textField.text = [textField.text stringByReplacingOccurrencesOfString:string withString:#"" options:NSCaseInsensitiveSearch range:range];
[self selectTextForInput:textField atRange:range];
return NO;
}
}
else if (textField.tab == PASSWORD_FIELD_TAG)
{
if([[NSPredicate predicateWithFormat:#"SELF MATCHES[cd] %#", #"[a-zA-Z0-9]{4,12}"] evaluateWithObject:string] == FALSE)
{
textField.text = [textField.text stringByReplacingOccurrencesOfString:string withString:#"" options:NSCaseInsensitiveSearch range:range];
[self selectTextForInput:textField atRange:range];
return NO;
}
}
else if (textField.tab == EMAIL_FIELD_TAG)
{
if([[NSPredicate predicateWithFormat:#"SELF MATCHES[cd] %#", #"[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"] evaluateWithObject:string] == FALSE)
{
textField.text = [textField.text stringByReplacingOccurrencesOfString:string withString:#"" options:NSCaseInsensitiveSearch range:range];
[self selectTextForInput:textField atRange:range];
return NO;
}
}
else if (textField.tab == AGE_FIELD_TAG)
{
if([[NSPredicate predicateWithFormat:#"SELF MATCHES[cd] %#", #"[1-100]"] evaluateWithObject:string] == FALSE)
{
textField.text = [textField.text stringByReplacingOccurrencesOfString:string withString:#"" options:NSCaseInsensitiveSearch range:range];
[self selectTextForInput:textField atRange:range];
return NO;
}
}
return YES;
}
// place the cursor at given possition
-(void)selectTextForInput:(UITextField *)input atRange:(NSRange)range {
UITextPosition *start = [input positionFromPosition:[input beginningOfDocument]
offset:range.location];
UITextPosition *end = [input positionFromPosition:start
offset:range.length];
[input setSelectedTextRange:[input textRangeFromPosition:start toPosition:end]];
}