You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 20:18:20