Search bar at the top of a UIPickerView in Swift

泄露秘密 提交于 2019-12-10 19:23:58

问题


So I have a textField, which when the user presses, it shows a UIPickerView, which is populated from an array.

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

I've not seen this done before so have no idea if it's possible?

Thanks in advance.


回答1:


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




回答2:


Here is an easy solution which I have used on my recent project. First of all you need to concentrate on the following points.

  1. Try to use UITextfield for better customization
  2. Use table view to populate data easily inside your main viewController class.
  3. Avoid using segue thing which is little bit annoying and old fashioned.
  4. 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 native filter method to filter form the array and reuse that.

Using Array of Array type Dictionary(Swift)

Concentrating 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)
}
}

Example to set over the storyboard.

Thanks.

Hope this helped.

Any Modification or suggestion our questions would be appreciated.




回答3:


  1. I added a custom header view for the table with a textField insted of searcontroller(searchbar) and cancel button programmatically with little custmization to the tableView.
  2. I added the following code to filter and get the updated search results

class ViewController: 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 its working perfectly



来源:https://stackoverflow.com/questions/30297135/search-bar-at-the-top-of-a-uipickerview-in-swift

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!