Reputation: 3755
I am working on new iOS application. In that app, I have 5 UITextFields and those are 1. first interest, second interest upto 5 interests.
I need to add Autocomplete for those 5 UITextFields. I have searched google for one day. I got some forums and tutorial for that. But I even have tried with Github links also.
According to my requirement, I have an array of data which is getting from my server. In that array, I have data like, coffee, cricket, etc. That is Autocomplete data. I need to display that array whenever user entered text in UITextField, if its related to my array of data, need to display below of that UITextFields.
For that purpose i used following code.
**// String in Search textfield
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
NSString *substring = [NSString stringWithString:textField.text];
substring = [substring stringByReplacingCharactersInRange:range withString:string];
[self searchAutocompleteEntriesWithSubstring:substring];
return YES;
}
**
// Take string from Search Textfield and compare it with autocomplete array
- (void)searchAutocompleteEntriesWithSubstring:(NSString *)substring {
// Put anything that starts with this substring into the autoCompleteArray
// The items in this array is what will show up in the table view
[autoCompleteArray removeAllObjects];
NSLog(@"autoCompleteArray %@",autoCompleteArray);
for(NSString *curString in elementArray) {
NSRange substringRangeLowerCase = [curString rangeOfString:[substring lowercaseString]];
NSRange substringRangeUpperCase = [curString rangeOfString:[substring uppercaseString]];
if (substringRangeLowerCase.length != 0 || substringRangeUpperCase.length != 0) {
[autoCompleteArray addObject:curString];
}
}
autoCompleteTableView.hidden = NO;
[autoCompleteTableView reloadData];
}
And I created UITableView as AutocompleteTableview
in ViewDidLoad
method.
**Issue is, if I type text as suppose "c", from my array of data displaying whatever text contains as "c" letter in tableview. But, if i typed "coff" no data displaying in that UITableView. Also how to validate which UITextField user clicking in tableviewdidselectrowatindexpath
delegate method. I tried with assigning tag for those UITextFields, but its working in UITextFields delegate methods only, not in other place. so, whenever i selected data from UITableView, first UITextField only taking data not other UITextField.
Please give your valuable suggestion, which is the best way to display the autocomplete for UITextfields
in iOS for multiple UITextfields and how to handle UITableView for displaying data. If anything mistakes in my content forgive me and please provide your valuable suggestions to fix this issue.
Thanks****
Upvotes: 2
Views: 18237
Reputation: 5063
Here is swift 3 inline autocomplete textfield example
create a project & add a textfield. Connect to viewcontroller named txtAutoComplete
View controller code bellow
import UIKit
class ViewController: UIViewController ,UITextFieldDelegate{
@IBOutlet weak var txtAutoComplete: UITextField!
var autoCompletionPossibilities = ["01921687433", "01553377642", "0155776622"]
var autoCompleteCharacterCount = 0
var timer = Timer()
override func viewDidLoad() {
super.viewDidLoad()
txtAutoComplete.delegate = self
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { //1
var subString = (textField.text!.capitalized as NSString).replacingCharacters(in: range, with: string)
subString = formatSubstring(subString: subString)
if subString.characters.count == 0 {
// 3 when a user clears the textField
resetValues()
} else {
searchAutocompleteEntriesWIthSubstring(substring: subString)
}
return true
}
func formatSubstring(subString: String) -> String {
let formatted = String(subString.characters.dropLast(autoCompleteCharacterCount)).lowercased().capitalized //5
return formatted
}
func resetValues() {
autoCompleteCharacterCount = 0
txtAutoComplete.text = ""
}
func searchAutocompleteEntriesWIthSubstring(substring: String) {
let userQuery = substring
let suggestions = getAutocompleteSuggestions(userText: substring)
if suggestions.count > 0 {
timer = .scheduledTimer(withTimeInterval: 0.01, repeats: false, block: { (timer) in //2
let autocompleteResult = self.formatAutocompleteResult(substring: substring, possibleMatches: suggestions)
self.putColourFormattedTextInTextField(autocompleteResult: autocompleteResult, userQuery : userQuery)
self.moveCaretToEndOfUserQueryPosition(userQuery: userQuery)
})
} else {
timer = .scheduledTimer(withTimeInterval: 0.01, repeats: false, block: { (timer) in //7
self.txtAutoComplete.text = substring
})
autoCompleteCharacterCount = 0
}
}
func getAutocompleteSuggestions(userText: String) -> [String]{
var possibleMatches: [String] = []
for item in autoCompletionPossibilities { //2
let myString:NSString! = item as NSString
let substringRange :NSRange! = myString.range(of: userText)
if (substringRange.location == 0)
{
possibleMatches.append(item)
}
}
return possibleMatches
}
func putColourFormattedTextInTextField(autocompleteResult: String, userQuery : String) {
let colouredString: NSMutableAttributedString = NSMutableAttributedString(string: userQuery + autocompleteResult)
colouredString.addAttribute(NSForegroundColorAttributeName, value: UIColor.green, range: NSRange(location: userQuery.characters.count,length:autocompleteResult.characters.count))
self.txtAutoComplete.attributedText = colouredString
}
func moveCaretToEndOfUserQueryPosition(userQuery : String) {
if let newPosition = self.txtAutoComplete.position(from: self.txtAutoComplete.beginningOfDocument, offset: userQuery.characters.count) {
self.txtAutoComplete.selectedTextRange = self.txtAutoComplete.textRange(from: newPosition, to: newPosition)
}
let selectedRange: UITextRange? = txtAutoComplete.selectedTextRange
txtAutoComplete.offset(from: txtAutoComplete.beginningOfDocument, to: (selectedRange?.start)!)
}
func formatAutocompleteResult(substring: String, possibleMatches: [String]) -> String {
var autoCompleteResult = possibleMatches[0]
autoCompleteResult.removeSubrange(autoCompleteResult.startIndex..<autoCompleteResult.index(autoCompleteResult.startIndex, offsetBy: substring.characters.count))
autoCompleteCharacterCount = autoCompleteResult.characters.count
return autoCompleteResult
}
}
Source code is given to GitHub.GitHub Link :https://github.com/enamul95/AutoCompleteTextField
Upvotes: 3
Reputation: 1179
Take two Global Array
NSMutableArray *muary_Interest_Main;
NSMutableArray *muary_Interest_Sub;
IN viewDidLoad Method
muary_Interest_Main = [[NSMutableArray alloc]initWithObjects:@"Cricket",@"Dancing",@"Painting",@"Swiming",@"guitar",@"movie",@"boxing",@"drum",@"hockey",@"chessing",@"gamming",
@"hunting",@"killing",@"shoping",@"jamm"@"zooming", nil];
muary_Interest_Sub = [[NSMutableArray alloc]init];
tbl_Search = [[UITableView alloc] initWithFrame:
CGRectMake(4, 200, 320, 120) style:UITableViewStylePlain];
tbl_Search.delegate = self;
tbl_Search.dataSource = self;
tbl_Search.scrollEnabled = YES;
[self.tbl_Search registerClass:[UITableViewCell class] forCellReuseIdentifier:@"CellIdentifier"];
[self.view addSubview:self.tbl_Search];
[tbl_Search setHidden:TRUE];
Now write a below code in textfield delegates.
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
NSLog(@"%d",textField.tag);
int_TextFieldTag = textField.tag;
[self searchText:textField replacementString:@"Begin"];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
tbl_Search.hidden = TRUE;
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
tbl_Search.hidden = TRUE;
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
[self searchText:textField replacementString:string];
return YES;
}
Write a method for search text
-(void) searchText:(UITextField *)textField replacementString:(NSString *)string
{
if(int_TextFieldTag == 1)
{
tbl_Search.frame = CGRectMake(4, 200, 320, 120);
}
else if(int_TextFieldTag == 2)
{
tbl_Search.frame = CGRectMake(4, 248, 320, 120);
}
else if(int_TextFieldTag == 3)
{
tbl_Search.frame = CGRectMake(4, 268, 320, 120);
}
else if(int_TextFieldTag == 4)
{
tbl_Search.frame = CGRectMake(4, 268, 320, 120);
}
else
{
tbl_Search.frame = CGRectMake(4, 268, 320, 120);
}
NSString *str_Search_String=[NSString stringWithFormat:@"%@",textField.text];
if([string isEqualToString:@"Begin"])
str_Search_String=[NSString stringWithFormat:@"%@",textField.text];
else if([string isEqualToString:@""])
str_Search_String = [str_Search_String substringToIndex:[str_Search_String length] - 1];
else
str_Search_String=[str_Search_String stringByAppendingString:string];
muary_Interest_Sub=[[NSMutableArray alloc] init];
if(str_Search_String.length>0)
{
NSInteger counter = 0;
for(NSString *name in muary_Interest_Main)
{
NSRange r = [name rangeOfString:str_Search_String options:NSCaseInsensitiveSearch];
if(r.length>0)
{
[muary_Interest_Sub addObject:name];
}
counter++;
}
if (muary_Interest_Sub.count > 0)
{
NSLog(@"%@",muary_Interest_Sub);
tbl_Search.hidden = FALSE;
[self.tbl_Search reloadData];
}
else
{
tbl_Search.hidden = TRUE;
}
}
else
{
[tbl_Search setHidden:TRUE];
}
}
Tableview Delegates methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [muary_Interest_Sub count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellIdentifier"];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"CellIdentifier"];
//cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
;
}
cell.textLabel.text = [muary_Interest_Sub objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.view endEditing:YES];
if(int_TextFieldTag == 1)
{
txt1.text=[muary_Interest_Sub objectAtIndex:indexPath.row];
}
else if(int_TextFieldTag == 2)
{
txt2.text=[muary_Interest_Sub objectAtIndex:indexPath.row];
}
else if(int_TextFieldTag == 3)
{
txt3.text=[muary_Interest_Sub objectAtIndex:indexPath.row];
}
else if(int_TextFieldTag == 4)
{
txt4.text=[muary_Interest_Sub objectAtIndex:indexPath.row];
}
else
{
txt5.text=[muary_Interest_Sub objectAtIndex:indexPath.row];
}
}
This also works on backspace of textfield. Try this. Hope this will suit your requirements.
Upvotes: 2
Reputation: 99
- (void)searchAutocompleteEntriesWithSubstring:(NSString *)substring{
//Assume this array is the autocomplete array for which you get data from server
NSMutableArray *autoCompleteArray = [[NSMutableArray alloc] initWithObjects:@"Coffee",@"Cricket",@"Volleyboll",nil];
text = [text stringByReplacingOccurrencesOfString:@" " withString:@""];
// This is to create predicate filter for getting matched text
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF beginswith[c] %@",text];
// store matched data for autocompletion in results array and reload data in your tableview based on this array's data
NSArray *resultArray = [[NSArray alloc] initWithArray:[autoCompleteArray filteredArrayUsingPredicate:predicate]];
}
Upvotes: 2
Reputation: 56
You can use the following links which describes how we can use autocompletion. I tried with the AutocompletionTableview (second link) and it worked perfectly.
https://github.com/EddyBorja/MLPAutoCompleteTextField
https://github.com/keyf/AutocompletionTableView
Upvotes: 0