无法将 'NSNull' 类型的值转换为 'NSString'

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

我遇到了一个非常奇怪的问题,我无法弄清楚这里出了什么问题。

这是我的代码

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()
}

程序在这一行崩溃

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

当我在搜索框中键入第一个字符时,一切正常,但是当我在 searchBox 程序中键入第二个字符时,它立即崩溃并给我这个错误

无法将类型 'NSNull' (0x1a03c3768) 的值转换为 'NSString' (0x1a03cd798)。

并且为了您的信息,countryNames 存在于 dict 变量中,但我不知道为什么它给我 null 值以及为什么城市名称能够成功工作,因为 country 也存在于我所在的同一个数组中获取城市

更新:

这一行打印国家名称成功

  print("countryName is \(countryName)")

好吧,他们告诉你问题出在哪里:你得到了一个 NSNull 类型的结果,而 NSNull 不能 转换为 NSString。

您很可能正在处理 JSON,并且 JSON 数据通常包含空值。

离开你的迷宫?和 !

写一些对你有帮助的代码。记住任何!如果您没有得到您期望的结果,将会使您的应用程序崩溃。

当你访问字典中的键 "name" 时,你需要处理以下情况:有一个字符串(对你来说很好),没有(键不存在,很常见),空(服务器明确告诉你什么都没有,很常见),一个数字,bool,dict 或数组。

对于每种情况,请告诉我您想要的结果是什么:崩溃?一个可选的字符串是 nil?一个空字符串?通常,如果它存在,您需要一个字符串,如果它是一个数字,则可能需要一个数字转换为字符串,如果键不存在或为 null,则可能是 nil 或一个空字符串,如果您得到一个崩溃或 nil布尔值、字典或数组。

然后写一个 returns 完全一样的函数。然后你使用它。当你写 (... as?NSString) 时!你告诉编译器如果它不是字符串你想要崩溃,这就是你得到的。

您在这一行收到了来自服务器的国家/地区列表

getCountriesNamesFromServer(searchWord)

但我认为它返回给您的列表没有完全设置所有数据。

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)
        }

在循环的第一次迭代中,name 值设置正确,因此它可以工作,但在我看来,在第二次迭代中,它是 null 并且你不能转换 NSNullNSString 所以应用程序崩溃。

在转换为 NSString 之前,如果您不确定服务器响应,您必须尝试字典是否包含 name 键以及是否设置了该值。如果是的话,你可以试试施法

如果需要,您还可以使用外部库 SwiftyJSON 来简化 JSON 响应的解析。

@gnasher729 解释的很好, 但要解决您的问题,您应该使用“?”而不是“!”

所以在解析下面代码中的数据时

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

使用代码作为

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

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

谢谢