Monday, July 15, 2013

Auto Search/Auto Complete using UITextField as SearchBar for iOS app


After a long gap, I made a time off  from my regular stuffs to write here few things. This time I choosed a topic  “Auto Search/Auto Complete” ,. You guyz already knew about this feature , if not, then auto search/Auto complete is the process of searching when you type some character in Search field. Auto search simply detects each of the character you type and starts searching. Moreover, When a user is entering data into a text field, it’s often nice to have the ability to auto complete with custom values based on what the user is entering, saving their time.

Auto Search  the name,  always sounds complicated  . Even I always thought doing auto search features in iOS app must be complicated but I was wrong . It is not hard as it sounds, and how I figured it out , I am explaining here with simply using UItextField and its native method.

Here are the step by step guidelines :

1.     First thing you need to create is UITextField which works as a search bar and UITableView for displaying your search results. And another thing is data source (Array/Dictionary) which has a collection of data from where we need to search  based on the name/strings which user types in text field.
2.     You can play with UItableView  in your own way. You simply can hide it first and when starts searching and finds result , you can unhide the table and reload the data. OR simply you can only add table view when search starts and remove it when we are done with the selection.
Here, I am using Hidden property of UItableView.
3.     Create UITextField , define <UITextFieldDelegate> in you .h file


          searchTxtFied = [[UITextField alloc] initWithFrame:CGRectMake(42, 11, 263, 30)];
          searchTxtFied.delegate = self;
          searchTxtFied.placeholder=@"Type a name"; 
      searchTxtFied.contentVerticalAlignment =UIControlContentVerticalAlignmentCenter;            
         searchTxtFied.backgroundColor = [UIColor clearColor];
           searchTxtFied.textColor = [UIColor darkGrayColor]; 
          searchTxtFied.returnKeyType = UIReturnKeyDone; 
         searchTxtFied.autocorrectionType = UITextAutocorrectionTypeNo;
         searchTxtFied.font = [UIFont fontWithName:@"Helvetica" size:13];
         [self.view addSubview: searchTxtFied];

Now , define a  action method for UITextField with its native control events ‘ Editing changed’.
[searchTxtFied addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];

4.     Define and declare your data source .
self.nameArray = [[NSArray alloc]  initWithArray:”your search data array”];
OR,
self.nameArray = [[NSArray alloc]  initWithArray:”your search data dictionaried(key/value pairs)”];

5.     Now here goes logic implementation
5.1 (If your data source is Array)
-(void)textFieldDidChange:(UITextField *)txtFld {
                        NSString * match = txtFld.text;
                       NSMutableArray *listFiles = [[NSMutableArray alloc]  init];
                     NSPredicate *sPredicate = [NSPredicate predicateWithFormat:
                                                                         @"SELF CONTAINS[cd] %@", match];
                       listFiles = [NSArray arrayWithArray:[self.nameArray  
                                             filteredArrayUsingPredicate:sPredicate]];
                      // Now if you want to sort search results Array
                      //Sorting NSArray having NSString as objects
                     NSMutableArray *sortedArray = [[NSMutableArray alloc]initWithArray: [listFiles 
                                   sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]];
                 //Use sorted array as your Table’s data source
                       -make your table unhidden: yourTbl.hidden = FALSE;
                      - reload your table  : [yourTbl reloadData];
}

5.2(If your data source is Dictionary)
If you want to search some specific  keywords from your dictionary  data source having  multiple key/value pairs , then use this method. For example lets say you have a array with multiple dictionary objects in it and each dictionary has a key/value pairs as :

               NSDictionary *temp1 = [NSDictionary
                                            dictionaryWithObjectsAndKeys:@"Sam",@"Name",@"1",@"UserID",nil];
              NSDictionary *temp2 = [NSDictionary 
                                          dictionaryWithObjectsAndKeys:@"Jacob",@"Name",@"2",@"UserID",nil];
              NSDictionary *temp3 = [NSDictionary  
                                       dictionaryWithObjectsAndKeys:@"Robert",@"Name",@"3",@"UserID",nil];
              NSDictionary *temp4 = [NSDictionary 
                                      dictionaryWithObjectsAndKeys:@"Samir",@"Name",@"4",@"UserID",nil];
            //self.nameArray is your data source
               self.nameArray = [NSArray arrayWithObjects:temp1,temp2,temp3,temp4, nil];

Now, If we are searching data based on the key named  “Name” then, our custom method should look like this:
-(void)textFieldDidChange:(UITextField *)txtFld {
                          NSString * match = txtFld.text;
                          NSMutableArray *listFiles = [[NSMutableArray alloc]  init];
                          NSPredicate *predicate =[NSPredicate predicateWithFormat:
                                                                         @"Name CONTAINS[cd] %@", match]; 
                           //or use Name like %@  //”Name” is the Key we are searching
                            listFiles = [NSArray arrayWithArray:[self.nameArray  
                                               filteredArrayUsingPredicate:predicate]]; 
                          // Now if you want to sort search results Array
                         //Sorting NSArray having NSDictionary as objects
                           NSSortDescriptor *sortDescriptor = [[[NSSortDescriptor alloc] 
                                                               initWithKey:@"Name"  ascending:YES] autorelease];
                           NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
                          NSArray *sortedArray = [listFiles sortedArrayUsingDescriptors:sortDescriptors];

                    //Use sortedArray as your Table’s data source
                        -make your table unhidden: yourTbl.hidden = FALSE;
                        - reload your table  : [yourTbl reloadData];
}


That’s it. Hope you got what you are looking for.  Thank you for stepping by.   
HAPPY CODING !!!

11 comments:

  1. hello sameer, can you explain me how to load that tableview. because my tableview is not loading but, when i use NSlog for sorted array it changes the values everytime i change the text in uitextfield.

    ReplyDelete
    Replies
    1. If sortedArray has a new value in it then simply reload your tableview after reading new value in sorted array:
      [yourTbl reloadData];

      Delete
  2. Hi Sameer, data not appear on the tableview,if
    possible plz provide source code.

    Thanks In advance

    ReplyDelete
    Replies
    1. If sortedArray has a new value in it then simply reload your tableview after reading new value in sorted array:
      [yourTbl reloadData];

      Delete
  3. hear is my code.
    my table reload successful but i also need the product id that matches with name..
    in databse name is not unique what should i do??


    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
    return 1;
    }
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
    if ([txtSearchBar isFirstResponder]) {
    return [sortedArray count];
    }
    else{
    return [arr_productID count];
    }
    }
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
    static NSString *CellIdentifier = @"Cell";
    ProductViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil) {
    cell = [[ProductViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    }
    if ([txtSearchBar isFirstResponder]) {
    NSLog(@"%@",sortedArray);
    cell.lblProductName.text = [NSString stringWithFormat:@"%@",[sortedArray objectAtIndex:indexPath.row]];
    }
    else
    {
    cell.lblProductID.text =[NSString stringWithFormat:@"%@",[arr_productID objectAtIndex:indexPath.row]];
    cell.lblProductName.text =[NSString stringWithFormat:@"%@",[arr_productName objectAtIndex:indexPath.row]];
    }

    return cell;
    }
    - (IBAction)txtReturn:(id)sender {
    [sender resignFirstResponder];
    }
    -(void)textFieldDidChange:(UITextField *)txtFld
    {
    NSString * match = txtFld.text;
    NSArray *listFiles = [[NSMutableArray alloc] init];
    NSPredicate *predicate =[NSPredicate predicateWithFormat:@"SELF CONTAINS[cd] %@", match];

    //or use Name like %@ //”Name” is the Key we are searching
    listFiles = [NSArray arrayWithArray:[arr_productName filteredArrayUsingPredicate:predicate]];

    // Now if you want to sort search results Array
    //Sorting NSArray having NSDictionary as objects
    sortedArray = [[NSMutableArray alloc]initWithArray: [listFiles sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]];

    //Use sortedArray as your Table’s data source
    NSLog(@"Array :%@",sortedArray);

    tbl_product.hidden =FALSE;
    [tbl_product reloadData];
    }

    ReplyDelete
  4. how can be use this code search some uiview

    ReplyDelete
  5. helo sameer can u provide me a video tutorial for the auto complete textfield for custom value(using NsArray)..
    thank u in advance !

    ReplyDelete
  6. hello sameer I want to search in uitableview having 26 section & which returns specific cell when searched . any suggestion?

    ReplyDelete
  7. HI Sameer , PLEASE REMOVE YOUR PHOTO. UNABLE TO SEEING CODE PROPERLY.

    ReplyDelete
  8. Wht if i want to do this as a Customized Textfield class as a library

    ReplyDelete