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

Swift 4.1调用通用Web API时类型转换错误及字段获取问题

解决Swift调用Web API时的类型转换错误并获取指定字段

嘿,我一眼就看出问题所在啦!你碰到的Could not cast value of type '__NSArrayM' to 'NSDictionary'错误,核心原因是:你调用的Web API返回的是一个JSON数组(外层用[]包裹),但你的代码却强行把它转换成了字典类型,这就导致了类型不匹配的崩溃。

先看一下API返回的核心结构:

[
  {
    "showBackgroundImage": "False",
    "backgroundColor": "4D5656",
    // ... 其他字段
  }
]

外层是数组,里面只有一个字典元素,所以我们得先解析成数组,再取出里面的字典。

下面是修正后的完整代码,我帮你调整了解析逻辑,并且实现了在Label上显示指定字段的功能:

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var lblDetail: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    @IBAction func btnClick(_ sender: Any) {
        guard let url = URL(string: "https://transsupp.com/testApp/ws17.ashx") else {
            // 处理URL无效的情况
            let alert = UIAlertController(title: "错误", message: "无效的API地址", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "确定", style: .cancel))
            present(alert, animated: true)
            return
        }
        
        let session = URLSession.shared
        let task = session.dataTask(with: url) { [weak self] (data, response, error) in
            guard let self = self else { return }
            
            if let error = error {
                // 处理网络错误
                DispatchQueue.main.async {
                    let alert = UIAlertController(title: "错误", message: error.localizedDescription, preferredStyle: .alert)
                    alert.addAction(UIAlertAction(title: "确定", style: .cancel))
                    self.present(alert, animated: true)
                }
                return
            }
            
            guard let data = data else {
                // 处理数据为空的情况
                DispatchQueue.main.async {
                    let alert = UIAlertController(title: "错误", message: "未获取到数据", preferredStyle: .alert)
                    alert.addAction(UIAlertAction(title: "确定", style: .cancel))
                    self.present(alert, animated: true)
                }
                return
            }
            
            do {
                // 第一步:先解析成包含字典的数组
                if let jsonArray = try JSONSerialization.jsonObject(with: data, options: []) as? [[String: Any]] {
                    // 第二步:取出数组中的第一个字典(因为API返回的数组里只有一个元素)
                    if let jsonDict = jsonArray.first {
                        // 第三步:提取需要的字段,注意处理可选值
                        let showBackgroundImage = jsonDict["showBackgroundImage"] as? String ?? "未知"
                        let backgroundColor = jsonDict["backgroundColor"] as? String ?? "未知"
                        
                        // 第四步:回到主线程更新UI(必须在主线程操作UI控件)
                        DispatchQueue.main.async {
                            self.lblDetail.text = "背景图显示状态:\(showBackgroundImage)\n背景颜色:\(backgroundColor)"
                        }
                    }
                }
            } catch {
                // 处理JSON解析错误
                DispatchQueue.main.async {
                    let alert = UIAlertController(title: "错误", message: "JSON解析失败", preferredStyle: .alert)
                    alert.addAction(UIAlertAction(title: "确定", style: .cancel))
                    self.present(alert, animated: true)
                }
            }
        }
        task.resume()
    }
}

我还额外做了这些优化:

  • 用guard let处理了URL、数据、self的可选值,避免强制解包导致的崩溃
  • 把所有UI操作都放在DispatchQueue.main.async里,符合iOS的UI线程规则
  • 给每个可能出错的环节都加了错误提示,提升用户体验
  • 处理了字段不存在的情况,用默认值替代,避免崩溃

这样修改后,点击按钮就能正确获取API返回的showBackgroundImage和backgroundColor字段,并在Label上显示啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:44:17