Atiffaniq
Atiffaniq

Reputation: 27

Dictionary search the key and get the value

I got a plist object which contains all the words key=english and value=malay and I assigned in to 2 different arrays which is english and malay. Now I want a textfield where I want to search the english word and print the malay word in the label.

import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate {

@IBOutlet weak var selectedLabel: UILabel!
@IBOutlet weak var searchText: UITextField!
@IBOutlet weak var wordTable: UITableView!
var english = [String]()
var malay = [String]()
var words: [String: String] = [:]
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    wordTable.dataSource = self
    wordTable.delegate = self
    searchText.delegate = self

    if let path = Bundle.main.path(forResource: "words", ofType: "plist"){
        if let plistData = FileManager.default.contents(atPath: path){
            do {
                let plistObject = try PropertyListSerialization.propertyList(from: plistData, options: PropertyListSerialization.ReadOptions(), format: nil)
                words = (plistObject as? [String: String])!
                english = [String] (words.keys)
                malay = [String] (words.values)

            } catch {
                print("Error Serialize")
            }
        } else {
            print("Error reading data")
        }
    } else {
        print("Property list")
    }
}

func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return english.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell: UITableViewCell!
    cell = tableView.dequeueReusableCell(withIdentifier: "tabelCell")
    if cell == nil {
        cell = UITableViewCell(
            style: UITableViewCellStyle.value2,
            reuseIdentifier: "tableCell")
        print("creating a table cell")
    }
    cell!.textLabel!.text = english[indexPath.row]
    cell!.detailTextLabel?.text = malay[indexPath.row]
    return cell!

}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    selectedLabel.text = malay[indexPath.row]

}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    // Hide the keyboard
    textField.resignFirstResponder()
    return true
}


@IBAction func searchBtn(_ sender: UIButton) {
    let result = words.filter {$0.key == searchText.text}
    if result.count > 0 {
        print(result)
        selectedLabel.text! = result.values //error

    } else {
        print("Not found")
    }
}

}

the output I expecting is textfield(Bus) which is english word then in the label show me the malay word(Bas)

plist

Upvotes: 0

Views: 165

Answers (2)

TheTiger
TheTiger

Reputation: 13354

You have a plist file as a Dictionary. So you can get the dictionary object from the plist file and already answer here.

Make a structure for better data binding.

struct Word {
    var english: String
    var malay: String
}

Then declare an array of words globally in your ViewController.

var words: [Word] = [] // An empty array

In viewDidLoad: fetch data from plist file.

override func viewDidLoad() {
super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    wordTable.dataSource = self
    wordTable.delegate = self
    searchText.delegate = self

    if let path = Bundle.main.path(forResource: "words", ofType: "plist") {
        if let plistData = FileManager.default.contents(atPath: path){
            do {
                guard let plistObject = try PropertyListSerialization.propertyList(from: plistData, options: [], format: nil) as? [String: String] else {
                    // Plist is not [String: String]
                    return
                }

                // Here you need to change the code. Converting the dictionary into struct array
                var words: [Word] = plistObject.map {Word(english: $0.key, malay: $0.value)}

                /// Then sort by english word if needed
                words.sorted {$0.english < $1.english}

            } catch {
                print("Error Serialize")
            }
        } else {
            print("Error reading data")
        }
    } else {
        print("Property list")
    }
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return words.count
}

Update your cell data as well.

cell!.textLabel!.text = words[indexPath.row].english
cell!.detailTextLabel?.text = words[indexPath.row].malay

And your button action with minor modification:

@IBAction func searchBtn(_ sender: UIButton) {
    let result = words.filter {$0.english == searchedText}
    if let word = result.first {
        selectedLabel.text = word.malay
    } else {
        selectedLabel.text = "" // No data found
    }
}

You can replace $0.english == searchedText with {$0.english.contains(searchedText)} if you want to filter with contains, But in that case you might get the multiple result. I assume that in your case you need it as a translator so use ==.

Upvotes: 1

Alexandr Kolesnik
Alexandr Kolesnik

Reputation: 2204

Why don't you search in your plist object? I think it is simpler

    @IBAction func searchBtn(_ sender: UIButton) {
        guard let words = plistObject as? [String: String], let key = searchText.text else { return }
        selectedLabel.text = words[key] ?? ""
    }

Something like this.

Upvotes: 1

Related Questions