Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift: Cannot convert value of type '[Any]' to specified type 'NSString'

General: I have a collections view app with several items from several plist depending which one the user picked. The plist is an array containing several arrays with multiple strings inside each array.

Problem: When inplementing a search bar to search through my collections (or plist), I get this error when following a tutorial.

I know this search bar code is meant to look for a string and not the string inside an array inside another array in the plist. So I'm looking for help to fix my error and the code.

Error:

Cannot convert value of type '[Any]' to specified type 'NSString'

This is the code what is causing the error.

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

    filtered = car.filter({ (text) -> Bool in
        let tmp: NSString = text // <-- ** Error is here **
        let range = tmp.range(of: searchText, options: NSString.CompareOptions.caseInsensitive)
        return range.location != NSNotFound
    })

    if(filtered.count == 0){
        searchActive = false;
    } else {
        searchActive = true;
    }

    self.finalCollectView.reloadData()
}

Rest of my code for SearchBar

func createSearchBar() {

    let mySearchBar = UISearchBar()
    mySearchBar.showsCancelButton = false
    mySearchBar.placeholder = "Search"
    mySearchBar.delegate = self
    mySearchBar.alpha = 1
    mySearchBar.tintColor = UIColor.black
    mySearchBar.searchFieldBackgroundPositionAdjustment = UIOffset(horizontal: 5, vertical: 0)

    self.navigationItem.titleView = mySearchBar
}

func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
    searchActive = true;
}

func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
    searchActive = false;
}

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
    searchActive = false;
}

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
    searchActive = false;
}

Code for plist

var filtered = [[Any]]()
var searchActive: Bool = false
var car = [[Any]]()
@IBOutlet weak var finalCollectView: UICollectionView!

override func viewDidLoad() {
    super.viewDidLoad()

    self.finalCollectView.delegate = self
    self.finalCollectView.dataSource = self

    readList(titlePlist: "car")
}

func readList(titlePlist: String) {

    let url = Bundle.main.url(forResource: titlePlist, withExtension: "plist")!
    do {
        let data = try Data(contentsOf:url)
        let sections = try PropertyListSerialization.propertyList(from: data, format: nil) as! [[Any]]

        car = sections

    } catch {
        print("This error must never occur: Reading plist", error)
    }

How the plist looks like

<plist> 
    <array>
        <array>
            <string>Name1</string>
            <string>Description</string>
        </array>
        <array>
            <string>Name2</string>
            <string>Description</string>
        </array>
        <array>
            <string>Name3</string>
            <string>Description</string>
        </array>
    </array>
</plist>

Search bar needs to search through the first string in each array. Thank you!

like image 499
WokerHead Avatar asked Dec 18 '25 06:12

WokerHead


2 Answers

In your func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String), modify filtering to:

filtered = car.filter({ (anArray) -> Bool in
    guard let firstString = (anArray.first as? String) else{
       return false
    }
    let tmp: NSString = firstString as NSString
    let range = tmp.range(of: searchText, options: NSString.CompareOptions.caseInsensitive)
    return range.location != NSNotFound
})
like image 99
Santhosh R Avatar answered Dec 19 '25 23:12

Santhosh R


If you only want to search through the first elements of the inner arrays of car, you should use flatMap to get the first elements. You should also cast the elements to NSString right away to avoid having to cast inside the filter.

filtered = car.flatMap({$0.first as? NSString})filter({ (text) -> Bool in...

However, your choice for a data structure is rather weird. Why would you declare car as [[Any]], when it only contains Strings and when the inner arrays clearly look like they should be a dictionary rather than an array? I would suggest you declare car as [[String:String]] and modify your .plist file accordingly.

like image 40
Dávid Pásztor Avatar answered Dec 19 '25 23:12

Dávid Pásztor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!