0
votes

I am new to swift and Xcode and I have been progressing along with an app that has tableview (of employees with first name space last name) created using a plist dictionary used as NSarray. I am trying to add a search feature.

Here is my code:

var employeeSearch = Array>()

let searchController = UISearchController(searchResultsController: nil)

func getSwiftArrayFromPlist() -> (Array<Dictionary<String,String>>) {

    let path = Bundle.main.path(forResource: "Sheet1", ofType: "plist")
    var arr: NSArray?
    arr = NSArray(contentsOfFile: path!)
    return (arr as? Array<Dictionary<String,String>>)!
}


func searchBarIsEmpty() -> Bool {
    // Returns true if the text is empty or nil
    return searchController.searchBar.text?.isEmpty ?? true
}

// no errors in above function

// I am getting a number of errors in the function below

func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
    employeeSearch = getSwiftArrayFromPlist().filter { $0["lastname".lowercased().contains(searchText.lowercased()]}
    print(employeeSearch)
    searchActive = !employeeSearch.isEmpty
    tblData.reloadData()
}
//getting many errors in above attempt to get a filtered array of dictionary to reload data in tableview 

Any help is appreciated. Thanks.

//Mar 1 - Finally this worked, but only equals condition was going without errors. My expectation was to have contains feature.. func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

    if searchBar.text == nil || searchBar.text == "" {
        isSearching = false
        view.endEditing(true)
        employee1View.reloadData()
    } else {
        isSearching = true
        employeeSearch = getSwiftArrayFromPlist()

        currentEmployeeSearch = employeeSearch.filter {($0["lastname"]?.lowercased() == searchText.lowercased())}
        //currentEmployeeSearch = employeeSearch.filter {($0["lastname"]?.lowercased().contains(searchText.lowercased())}
        employee1View.reloadData()
    }
}

// *****************************************

2
Note: the var declaration shows incorrectly in this post. it s var employeeSearch = Array<Dictionary<String,String>>() - Dharma
I moved my comment to an answer for readability. - Steve
Not related but why do you recreate the array from disk in each call of textDidChange? That unnecessarily expensive. And it's highly recommended to use PropertyListSerialization or even PropertyListDecoder rather the NSArray convenience API - vadian

2 Answers

0
votes

I think that the filter has incorrect brackets. I believe

employeeSearch = getSwiftArrayFromPlist().filter { $0["lastname".lowercased().contains(searchText.lowercased()]}

should be

employeeSearch = getSwiftArrayFromPlist().filter { $0["lastname"].lowercased().contains(searchText.lowercased())}

Updated answer to help with handling optionals

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    employeeSearch = getSwiftArrayFromPlist()

    guard !searchText.isEmpty else {
        // In here set the array used in the rest of the app equal to employeeSearch
        return employeeSearch
    }

    currentEmployeeSearch = employeeSearch.filter{
        guard let lowerCasedLastName = $0["lastname"].lowercased() else {
            //If we didn't get a lowercased last name from the employeeSearchArray we return false
            // false means we don't want to include that in the search results array
            return false }
        //If we do have a lowerCasedLastName lets see if it contains the search text
        return lowerCasedLastName.contains(searchText.lowercased())
    }

    employee1View.reloadData()

    //Note: Depending on what array the rest of your application uses you will want to set it equal to the value returned from the filter or returned from the else block of the guard against searchText being empty.
}
0
votes

Steve's solution worked. Thank you very much! //********************** func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {

    if searchBar.text == nil || searchBar.text == "" {
        isSearching = false
        view.endEditing(true)
        employee1View.reloadData()
    } else {
        isSearching = true
        employeeSearch = getSwiftArrayFromPlist()

        //currentEmployeeSearch = employeeSearch.filter {($0["lastname"]?.lowercased() == searchText.lowercased())}
        currentEmployeeSearch = employeeSearch.filter {($0["lastname"]?.lowercased().contains(searchText.lowercased())) ?? false}
        employee1View.reloadData()
    }
}