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

iOS开发报错signal SIGABRT:无法将NSNull类型转换为NSString

问题分析与修复方案

你的代码触发signal SIGABRT的核心原因是过度使用强制解包符!,一旦某个可选值为nil或者类型转换失败,就会直接崩溃。以下是具体问题和修复步骤:

主要问题点

  • 直接强制解包data!:如果网络请求返回的data为空,这里会崩溃
  • 强制转换jsonArray as! [Any]:如果返回的JSON不是数组类型(比如是字典),转换失败会崩溃
  • 强制转换jsonResult as! [String:String]:如果JSON数组里的元素不是[String:String]类型(比如某个值是数字),转换失败会崩溃
  • 强制解包字典取值jsonDict["Name"]!:如果键名拼写错误或者对应值为nil,会崩溃
  • 强制调用delegate!.itemsDownloaded:如果delegate未设置,会崩溃

修复后的代码

protocol HomeModelCleanersDelegate: AnyObject {
    func itemsDownloaded(cleaners: [Cleaner])
}

class HomeModelCleaners: NSObject {
    weak var delegate: HomeModelCleanersDelegate? // 用weak避免循环引用

    func getItems() {
        let serviceUrl = "https://absolutecleandatabase.com/Cleaners.php"
        
        guard let url = URL(string: serviceUrl) else {
            print("URL格式错误")
            return
        }
        
        let session = URLSession(configuration: .default)
        let task = session.dataTask(with: url) { [weak self] data, response, error in
            guard let self = self else { return }
            
            if let error = error {
                print("网络请求错误:\(error.localizedDescription)")
                return
            }
            
            guard let data = data else {
                print("未获取到数据")
                return
            }
            
            self.parseJson(data: data)
        }
        
        task.resume()
    }
  
    func parseJson(data: Data) {
        var clArray = [Cleaner]()
        
        do {
            // 先尝试解析为数组,避免强制转换
            guard let jsonArray = try JSONSerialization.jsonObject(with: data) as? [[String: Any]] else {
                print("JSON格式不是预期的数组类型")
                return
            }
            
            for jsonResult in jsonArray {
                // 安全提取每个字段,处理类型转换和空值
                guard let name = jsonResult["Name"] as? String,
                      let startingTime = jsonResult["Starting Time"] as? String,
                      let finishingTime = jsonResult["Finishing Time"] as? String,
                      let hours = jsonResult["Hours"] as? String,
                      let date = jsonResult["Date"] as? String else {
                    print("某个字段缺失或类型不匹配,跳过当前条目")
                    continue
                }
                
                let cl = Cleaner(name: name, startingTime: startingTime, finishingTime: finishingTime, hours: hours, date: date)
                clArray.append(cl)
            }
            
            // 用可选链式调用安全通知delegate
            delegate?.itemsDownloaded(cleaners: clArray)
            
        } catch {
            print("JSON解析错误:\(error.localizedDescription)")
        }            
    }
 }

关键修改说明

  1. Delegate添加AnyObject并设为weak:避免循环引用,防止内存泄漏
  2. 使用guard let替代强制解包:提前处理可选值为空的情况,避免崩溃
  3. JSON解析用[[String: Any]]而非[Any]:更准确匹配JSON结构,同时避免类型转换失败
  4. 字段提取时做类型检查:确保每个字段都是预期的String类型,缺失或类型不符时跳过当前条目
  5. 可选链式调用delegate?.itemsDownloaded:即使delegate未设置也不会崩溃
  6. 添加错误打印:方便排查网络请求、JSON解析过程中出现的问题

另外,建议你先通过浏览器访问https://absolutecleandatabase.com/Cleaners.php,查看返回的JSON结构是否和你预期的一致——这很可能是和主故事板代码差异的核心原因(比如字段名拼写、数据类型不同)。

内容的提问来源于stack exchange,提问作者Phrogal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 02:01:10