Could not cast value of type 'NSNull' to 'NSString'

hellosheikh picture hellosheikh · Feb 24, 2016 · Viewed 8k times · Source

I am having a very weird problem which I am not able to figure it out of what is going wrong here.

Here is my code

func updateSearchResultsForSearchController(searchController: UISearchController) {
    filterTableData.removeAll(keepCapacity: false)
    let searchWord = searchController.searchBar.text!

    getCountriesNamesFromServer(searchWord)

    let searchPredict = NSPredicate(format: "SELF CONTAINS[c] %@", searchController.searchBar.text!)

     newTableData = [String]()

    for var i = 0; i < self.dict.count - 1; i++ {

        let cityName = (((self.dict["\(i)"] as?NSDictionary)!["City"] as?NSDictionary)!["name"] as?NSString)! as String
       let countryName = (((self.dict["\(i)"] as?NSDictionary)!["Country"] as?NSDictionary)!["name"] as?NSString)! as String

            print("countryName is \(countryName)")





    newTableData.append(cityName)
    }
    print("newTableData is \(newTableData)" )
    let array = (newTableData as NSArray).filteredArrayUsingPredicate(searchPredict)
    print("array is\(array)")
    filterTableData = array as! [String]
    self.tableView.reloadData()
}

Program is crashing at this line

let countryName = (((self.dict["\(i)"] as?NSDictionary)!["Country"] as?NSDictionary)!["name"] as?NSString)! as String

when I type first character in the search box all works fine but as soon as I type second character in the searchBox program crashes and it gives me this error

Could not cast value of type 'NSNull' (0x1a03c3768) to 'NSString' (0x1a03cd798).

and for your Information countryNames exist in the dict variable but I don't know why its giving me null value and why city name is successfully working because country also exist in the same array from which I am getting the city

UPDATE:

This line prints country name successfully

  print("countryName is \(countryName)")

Answer

gnasher729 picture gnasher729 · Feb 24, 2016

Well, they tell you what the problem is: You've got a result of type NSNull, and NSNull cannot be converted to NSString.

Most likely you are processing JSON, and JSON data often contains null values.

Go away from your labyrinth of ? and !

Write some code that helps you. Remember that any ! will crash your application if you don't get what you expect.

When you access the key "name" in a dictionary, you need to handle the case that there is a string (nice for you), nothing (key doesn't exist, very common), null (the server tells you explicitly that there is nothing, very common), a number, bool, dict or array.

For each of these cases, tell me what you want as a result: A crash? An optional string that is nil? An empty string? Typically you want a string if it is there, possibly a number converted to a string if it is a number, and either nil or an empty string if the key isn't there or null, and either a crash or nil if you get a bool, dictionary or array.

Then write a function that returns exactly that. And then you use it. When you write (... as? NSString)! you tell the compiler that you want a crash if it's not a string, and that's what you got.