3

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

这是我的代码

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变量中,但我不知道为什么它给我空值以及为什么城市名称成功工作,因为国家也存在于我从中获取城市的同一数组中

更新:

此行成功打印国家名称

  print("countryName is \(countryName)")
4

3 回答 3

4

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

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

远离你的迷宫?和 !

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

当您访问字典中的键“名称”时,您需要处理存在字符串(对您来说很好),没有(键不存在,很常见),null(服务器明确告诉您有什么都不是,很常见)、数字、布尔值、字典或数组。

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

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

于 2016-02-24T11:04:24.343 回答
1

@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 ?? ""

谢谢

于 2019-01-23T08:27:28.093 回答
0

您在此行从您的服务器收到了国家/地区列表

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并且您不能强制NSNull转换,NSString因此应用程序崩溃。

在转换为 之前NSString,如果您不确定服务器响应,则必须尝试字典是否包含name键以及值是否已设置。如果是,您可以尝试投射它。

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

于 2016-02-24T11:25:10.873 回答