Search bar at the top of UIPickerView in Swift

So I have a textField that, when the user clicks, shows a UIPickerView that is populated from an array.

Is it possible for there to be a search bar at the top of the pickerView so that the user can search for something in the pickerView?

I haven't seen this before, so I don't know if this is possible?

Thanks in advance.

+3


source to share


3 answers


UIPickerView

is really intended for multiple options - if you need to present something that has more options, I would suggest a table view with a search bar. The Search Bar Tutorial is a good start.



+4


source


Here is a simple solution that I used in my recent project. First of all, you need to focus on the following points.

  • Try using UITextfield for better customization
  • Use a table view to easily populate data inside the main viewController class.
  • Avoid using things that are a little annoying and old-fashioned.
  • Try to make your code more realistic and hassle-free.

First things first : - I am using Xcode 7.2.2 with Swift 2.1

Using the built-in filtering method to filter the array shape and reuse.

Using Array of Array type Dictionary (Swift)

Focusing on the above points .. :)

Here is my class file. Go through the code and you will understand ...



import UIKit

class ComposeMessageClass: UIViewController, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource {
var filtered = [[String : String]]()
let customerNameForSearch: [[String : String]] = [["name": "Tuhin"], ["name": "Superman"], ["name" : "Rahul"], ["name": "Batman"], ["name": "Spiderman"]]
let customerNameToSearchTemp = ["Tuhin", "Superman", "Rahul", "Batman", "Spiderman"]
var searchActive: Bool = false
@IBOutlet weak var autofillTable: UITableView!
@IBOutlet weak var autofillTableView: UIView!

override func viewDidLoad() {
    super.viewDidLoad()
    self.autofillTableView.hidden = true
    self.autofillTable.delegate = self
    self.autofillTable.dataSource = self
    self.autofillTable.backgroundColor = tableViewBackGroundColor
    self.autofillTable.separatorColor = tableViewSeperatorColor
    self.autofillTable.layer.borderColor = tableViewBorderColor
    }
}

override func viewWillAppear(animated: Bool) {
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

override func viewDidAppear(animated: Bool) {
}

func textFieldDidBeginEditing(textField: UITextField) {
}

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    var updatedTextString : NSString = textField.text! as NSString
    updatedTextString = updatedTextString.stringByReplacingCharactersInRange(range, withString: string)
    self.filtered.removeAll()
    self.customerNameToSearchTemp.filter({ (text) -> Bool in
        let tmp: NSString = text
        let range = tmp.rangeOfString(updatedTextString as String, options: NSStringCompareOptions.CaseInsensitiveSearch)
        if range.location != NSNotFound{
            let dataArr = ["name": tmp as String]
            filtered.append(dataArr)

        }
        return false
      }
    })

    if(filtered.count == 0){

        filtered = [["name" : "No results found"]]
        searchActive = true
    } else {
        searchActive = true;
    }
    self.autofillTable.reloadData()
    return true
}

func textFieldDidEndEditing(textField: UITextField) {

}

func textFieldShouldReturn(textField: UITextField) -> Bool {
   textField.resignFirstResponder()
    return true
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

internal func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if(searchActive) {
        return self.filtered.count
    }
    return self.customerNameForSearch.count

}
internal func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell:UITableViewCell = self.autofillTable.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
    cell.backgroundColor = UIColor.clearColor()
    cell.textLabel!.textColor = tableViewCellTextColorGreen
    cell.textLabel!.textAlignment = .Center
    cell.selectionStyle = .None
    cell.textLabel!.font = UIFont(name: "System", size:17)
    if(searchActive){
        if filtered[indexPath.row]["name"]! == "No results found"{
            cell.textLabel!.text = self.filtered[indexPath.row]["name"]!
            cell.userInteractionEnabled = false
        }else{
            cell.userInteractionEnabled = true
            cell.textLabel?.text = self.filtered[indexPath.row]["name"]!
        }
    } else {
        cell.userInteractionEnabled = true
        cell.textLabel?.text = self.appDelegateObjForThisClass.customerNameForSearch[indexPath.row]["name"]!
    }
    return cell
}
internal func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    if(self.autofillTable.respondsToSelector(Selector("setSeparatorInset:"))){
        self.autofillTable.separatorInset = UIEdgeInsetsZero
    }

    if(self.autofillTable.respondsToSelector(Selector("setLayoutMargins:"))){
        self.autofillTable.layoutMargins = UIEdgeInsetsZero
    }

    if(cell.respondsToSelector(Selector("setLayoutMargins:"))){
        cell.layoutMargins = UIEdgeInsetsZero
    }
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
    let cell  = tableView.cellForRowAtIndexPath(indexPath)
    cell?.backgroundColor = UIColor.clearColor()
    cell?.textLabel?.textColor = tableViewCellTextColorGreen
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    let cell  = tableView.cellForRowAtIndexPath(indexPath)
    cell?.backgroundColor = UIColor.blackColor()
    cell?.textLabel?.textColor = tableViewCellTextColorWhite
    self.selectedCustomerId.removeAll()
    if(searchActive){
        self.contactNameTxtFld.text = self.filtered[indexPath.row]["name]!
    }else{
        self.contactNameTxtFld.text = self.appDelegateObjForThisClass.customerNameForSearch[indexPath.row]["name"]!
    }
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?){
    self.view.endEditing(true)
}
}

      

Installation example above a storyboard.

enter image description here

Thank.

Hope this helped.

Any modification or suggestion of our questions would be appreciated.

0


source


  • I added a custom header for a table with a textbox instested of searcontroller (searchbar) and programmatically unclipped the button with a little looping in the tableView.
  • I've added the following code to filter and get updated search results.

ViewController class: UIViewController, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource {

let speciality=["Andhra","Bhihar","uttharPradesh","kerala","karnataka","kashmir","thamilnadu","assam","jarkhand","dolapure","manjil","udaypoor","sholapoor","Atthapure","Barampure","Khasi"]

var filteredArray = [String]()

var shouldShowSearchResults = false

var tableView:UITableView!

var yaxis:CGFloat=10

var txtdateOfOperation:UITextField!

var searchTextField:UITextField!

var cancelButton:UIButton!

override func viewDidLoad() {

    let dateOfOperationLabel=UILabel(frame:CGRectMake(8,100,200,16))
    dateOfOperationLabel.text="State"
    dateOfOperationLabel.textColor=UIColor.blackColor()
    dateOfOperationLabel.textAlignment=NSTextAlignment.Left
    dateOfOperationLabel.font = UIFont.systemFontOfSize(13.0)
    dateOfOperationLabel.numberOfLines = 0;
    self.view.addSubview(dateOfOperationLabel)

    txtdateOfOperation=UITextField(frame: CGRectMake(8,130,300,28))
    txtdateOfOperation.borderStyle=UITextBorderStyle.RoundedRect
    txtdateOfOperation.returnKeyType=UIReturnKeyType.Done
    txtdateOfOperation.userInteractionEnabled=true
    txtdateOfOperation.keyboardType=UIKeyboardType.NumberPad
    self.view.addSubview(txtdateOfOperation)

    tableView=UITableView(frame: UIScreen.mainScreen().bounds, style: UITableViewStyle.Plain)
    tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
    tableView.delegate=self
    tableView.dataSource=self
    tableView.reloadData()

    let view=UIView(frame:CGRectMake(0,0,UIScreen.mainScreen().bounds.width,35))

    view.backgroundColor=UIColor.lightGrayColor()

    searchTextField=UITextField(frame:CGRectMake(8,3,view.bounds.width-70,28))

    searchTextField.borderStyle=UITextBorderStyle.RoundedRect
    searchTextField.returnKeyType=UIReturnKeyType.Done
    searchTextField.userInteractionEnabled=true
    searchTextField.delegate=self
    searchTextField.placeholder="Search Here..."
    searchTextField.clearButtonMode = .WhileEditing

    searchTextField.leftViewMode = UITextFieldViewMode.Always

    searchTextField.leftView = UIImageView(image: UIImage(named: "search-icon"))

    searchTextField.addTarget(self, action: #selector(searchTextFieldDidBeginEdit), forControlEvents: UIControlEvents.EditingChanged)

    view.addSubview(searchTextField)

    cancelButton=UIButton(frame:CGRectMake(view.bounds.width-65,3,70,28))
    cancelButton.setTitle("Cancel", forState: UIControlState.Normal)
    cancelButton.setTitleColor(UIColor.grayColor(), forState: UIControlState.Normal)
    cancelButton.addTarget(self, action: #selector(searchBarCancelButton_Click), forControlEvents: UIControlEvents.TouchUpInside)
    cancelButton.userInteractionEnabled=false

    view.addSubview(cancelButton)

    tableView.tableHeaderView = view

    txtdateOfOperation.inputView=tableView

    searchTextField.inputView=tableView

    self.tableView.reloadData()

    }


func textFieldDidBeginEditing(textField: UITextField) {

    shouldShowSearchResults = true
    cancelButton.userInteractionEnabled=true
    cancelButton.setTitleColor(UIColor(red: 51/255, green: 153/255, blue: 255/255, alpha: 1.0), forState: UIControlState.Normal)
    tableView.reloadData()
}

func textFieldDidEndEditing(textField: UITextField) {
   cancelButton.setTitleColor(UIColor.grayColor(), forState: UIControlState.Normal)
}

func searchTextFieldDidBeginEdit(textField:UITextField) {

  if let searchText=textField.text{

    filteredArray = speciality.filter({ (country) -> Bool in
        let countryText: NSString = country

        return (countryText.rangeOfString(searchText, options: NSStringCompareOptions.CaseInsensitiveSearch).location) != NSNotFound
    })
        tableView.reloadData()
    }
}

func searchBarCancelButton_Click(){
    searchTextField.text=nil
    searchTextField.resignFirstResponder()
    shouldShowSearchResults = false
    tableView.reloadData()
}


func textFieldShouldReturn(textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    return true
}


func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}


func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if shouldShowSearchResults {
        return filteredArray.count
    }
    else {
        return speciality.count
    }
}


func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)

    if shouldShowSearchResults {
        cell.textLabel?.text = filteredArray[indexPath.row]
    }
    else {
        cell.textLabel?.text = speciality[indexPath.row]
    }

    return cell
}


func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    return 60.0
}

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {


    if shouldShowSearchResults{
        txtdateOfOperation.text=filteredArray[indexPath.row]
        searchTextField.text=nil
        searchTextField.resignFirstResponder()
        txtdateOfOperation.resignFirstResponder()
        shouldShowSearchResults=false
        filteredArray=[String]()
        tableView.reloadData()
    }
    else{

        txtdateOfOperation.text=speciality[indexPath.row]
        searchTextField.resignFirstResponder()
        tableView.resignFirstResponder()
        txtdateOfOperation.resignFirstResponder()
    }
}

      

}

I tested it and it worked fine

0


source







All Articles