Swift API调用遇Thread 1: signal SIGABRT错误,求解决方案
解决Swift API调用中的Thread 1: signal SIGABRT错误
问题核心
你遇到的崩溃是类型强制转换失败,错误提示Could not cast value of type '__NSDictionaryI' to 'NSString'明确说明:你试图把字典类型的name字段直接转成字符串,但Rest Countries API返回的name是嵌套字典;同时capital字段是字符串数组(部分国家有多个首都),你用as!强制解包的操作,一旦类型不匹配就会触发SIGABRT崩溃。
具体修正方案
方案1:修正手动解析逻辑(基础版)
针对API返回的结构调整解析代码,用可选绑定替代强制解包,避免崩溃:
import UIKit class ViewController: UIViewController { @IBOutlet weak var myLabel: UILabel! var fetchedCountry = [Country]() override func viewDidLoad() { super.viewDidLoad() parseData() } func parseData(){ let url = "https://restcountries.com/v3.1/all" guard let urlObj = URL(string: url) else { print("无效URL") return } var request = URLRequest(url: urlObj) request.httpMethod = "GET" let session = URLSession(configuration: .default, delegate: nil, delegateQueue: OperationQueue.main) let task = session.dataTask(with: request) { data, response, error in if let error = error { print("请求错误: \(error.localizedDescription)") return } guard let data = data else { print("无返回数据") return } do{ guard let fetchData = try JSONSerialization.jsonObject(with: data) as? [[String: Any]] else { print("数据格式错误") return } DispatchQueue.main.async { for eachFetchedCountry in fetchData { // 解析国家名称:name是嵌套字典,提取common字段 guard let nameDict = eachFetchedCountry["name"] as? [String: Any], let countryName = nameDict["common"] as? String else { continue // 解析失败则跳过当前条目 } // 解析首都:capital是数组,取第一个元素,无首都则显示默认值 let capitalName = (eachFetchedCountry["capital"] as? [String])?.first ?? "无首都" self.fetchedCountry.append(Country(country: countryName, capital: capitalName)) } print(self.fetchedCountry) } } catch{ print("解析错误: \(error.localizedDescription)") } } task.resume() } } class Country { var country : String var capital : String init(country: String, capital: String){ self.capital = capital self.country = country } }
方案2:使用Codable解析(推荐)
Codable是Swift处理JSON的标准方案,类型安全且代码更简洁,完全避免手动解析的类型错误:
import UIKit class ViewController: UIViewController { @IBOutlet weak var myLabel: UILabel! var fetchedCountry = [CountryModel]() override func viewDidLoad() { super.viewDidLoad() parseData() } func parseData(){ let url = "https://restcountries.com/v3.1/all" guard let urlObj = URL(string: url) else { print("无效URL") return } URLSession.shared.dataTask(with: urlObj) { data, response, error in if let error = error { print("请求错误: \(error.localizedDescription)") return } guard let data = data else { print("无返回数据") return } do{ // 用Codable直接解析成模型数组 let countries = try JSONDecoder().decode([Country].self, from: data) DispatchQueue.main.async { // 转换为你原来的CountryModel结构 self.fetchedCountry = countries.map { CountryModel(country: $0.name.common, capital: $0.capital?.first ?? "无首都") } print(self.fetchedCountry) } } catch{ print("解析错误: \(error.localizedDescription)") } }.resume() } } // 适配API结构的Codable模型 struct Country: Codable { let name: Name let capital: [String]? } struct Name: Codable { let common: String } // 保留你原来的Country类 class CountryModel { var country : String var capital : String init(country: String, capital: String){ self.capital = capital self.country = country } }
关键注意事项
- 永远不要用
as!强制类型转换,改用as?配合可选绑定,防止类型不匹配导致崩溃 - 调用API前务必确认返回的JSON结构,可以直接访问
https://restcountries.com/v3.1/all查看字段格式 - Codable是Swift处理JSON的最优方案,比手动解析更安全、易维护
内容的提问来源于stack exchange,提问作者mustafagoktugibolar
相关产品推荐
相关产品推荐

