Search Bar

How do I get a search bar to search through a dictionary and display the value in a text field when the dictionaries key is entered in the search bar? The dictionary is on a different view controller.

Replies

What is exactly your problem ?


Get access to the dictionary in the other view controller ?

If so, you could use a delegate to access data from the other controller

I have a search bar and a text view on one view controller. I have the search bar and the text view named in one file (a class). I have my dictionaries in a different file (a different class). What I want is when the user types in the search bar I want the search bar to search through all of my dictionary keys and return the value of that particular keys value in the text view. How do I do that?

What is the type of class which has the dictionary ?

Show the code to clarify.


Is it a viewController ? -> MyControllerWithDict

If so, delegation is a good way to go


Is it a completely custom class ? => MyPrivateClass


If so, you have probably created an instance of the class in the controller with the navigation bar ?

var myInstanceOfPrivateClass: MyPrivateClass

If so, simply use

myInstanceOfPrivateClass.theDictionary[theKey]

Both of the files are .swift files. Both of the classes are of type UIViewController.


Class Home: UIViewController has the search bar and text field.


Class IntroductionToComputers: UIViewController has the dictionaries.


I want the Search Bar to search through multiple dictionaries for the key typed and display the value in the text field.


import UIKit

class Home: UIViewController, UISearchBarDelegate {
    
    
    @IBOutlet weak var searchBar: UISearchBar!
    
    @IBOutlet weak var txtSearchResults: UITextView!
    
    var isSearching: Bool = false
    var searchResults: [String: String] = ["":""]
    
    
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        if searchBar.text == nil || searchBar.text == "" {
            isSearching = false
            view.endEditing(true)
        }
        else {
            isSearching = true
        }
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }
    
    func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool {
        self.view.endEditing(true)
        return true
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        searchBar.delegate = self
        searchBar.returnKeyType = UIReturnKeyType.done
    }

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




import UIKit

class IntroductionToComputers: UIViewController {
    
   
     let favoritesDictionary = ["Color":"Red", "Car":"Ferarri", "Food":"Pizza", "Sport":"Football", "Music","Rock"]

     let schoolScheduleDictionary: ["Term 1":"Math", "Term 2":"English", "Term 3":"Science", "Term 4":"Art",
          "Term 5":"Gym"]



override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

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


}

Well, so use delegates.


Define a protocol, before IntroductionToComputers class declaration


protocol getDataProtocol {

  func readDict(key: String) -> String
}


make IntroductionToComputers conform to it and implement the func


class IntroductionToComputers: UIViewController, getDataProtocol {

func readDict(key: String) -> String {

     if let value = favoritesDictionary[key] { return value }
     if let value = schoolScheduleDictionary[key] { return value }
     return ""          //  nothing found
}


In Home class, create a delegate var


class Home: UIViewController, UISearchBarDelegate {
     var delegate: getDataProtocol?

     //      in search, use the delegate to retrieve info

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        if searchBar.text == nil || searchBar.text == "" {
            isSearching = false
            view.endEditing(true)
        }
        else {
            isSearching = true
             let readInDictionary = delegate?.readDict(searchBar.text!)
          // Use the value as you need
        }
}



There is a lst thing missing: setting the delegate


For this, we need to know where you instantiate the 2 view controllers. Do you segue from IntroductionToComputers to the Home ?

In that case, in the prepare (forSegue), in IntroductionToComputers, you would have


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let destination = segue.destination as? Home {
            destination.delegate = self
        }
    }



Or do you instantiate another way ? Please explain.


Note:

Something is not clear in your code: how do you use the dictionaries in IntroductionToComputers ? I do not see them used anywhere.


Another approach would be to define a model


class DataDict {
    let favoritesDictionary = ["Color":"Red", "Car":"Ferarri", "Food":"Pizza", "Sport":"Football", "Music","Rock"]

     let schoolScheduleDictionary: ["Term 1":"Math", "Term 2":"English", "Term 3":"Science", "Term 4":"Art",
          "Term 5":"Gym"]

     func readDict(key: String) -> String {

          if let value = favoritesDictionary[key] { return value }
          if let value = schoolScheduleDictionary[key] { return value }
          return ""          //  nothing found
     }

}


Then in Home class, create an instance of the model


class Home: UIViewController, UISearchBarDelegate {

     var dataModel: DataDict?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        searchBar.delegate = self
        searchBar.returnKeyType = UIReturnKeyType.done
        dataModel = DataDict()
    }

You can now access in the search


    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        if searchBar.text == nil || searchBar.text == "" {
            isSearching = false
            view.endEditing(true)
        }
        else {
            isSearching = true
             let readInDictionary = dataModel.readDict(searchBar.text!)
          // Use the value as you need
        }
}