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
相关产品推荐
相关产品推荐

