Xcode Swift开发:将JSON响应转换为UIPickerView数组数据源
双UIPickerView级联选择的JSON解码问题修复
实现需求
- 页面放置两个并排的
UIPickerView,分别用于选择主类型(Type)和子类型(Subtype) - 两个选择器的数据源均为字符串数组,初始定义:
var typePickerData: [String] = [String]() var subtypePickerData: [String] = [String]()
- 主类型选择器的数据源为固定字符串数组,示例值:
typePickerData = ["Monitor","Keyboard","Mouse"]
- 触发子类型接口请求的时机:
viewDidLoad生命周期执行时、用户切换主类型选中项时 - 接口返回子类型数据后,需要刷新子类型选择器展示最新选项
问题排查
最初实现时直接尝试将接口返回数据解码为字符串数组[String],代码如下:
let decoder = JSONDecoder() if let jsonResponse = try? decoder.decode([String].self, from: data) { print("parse subtype response \(jsonResponse)") subtypePickerData = jsonResponse DispatchQueue.main.async { self.subtypePicker.reloadAllComponents() } }
这段代码始终无法进入解码成功的分支,打印原始返回数据后确认根因:接口返回的不是纯字符串数组,而是携带name字段的对象数组,原始返回结构如下:
result Optional(<__NSArrayM 0x281370e70>( { name = Monitor; }, { name = "AV Accessories"; }, { name = Computer; }, { name = "Monitor Stands"; }, { name = "Bracket/Mount"; }, { name = Screen; } ))
修复方案
调整解码逻辑,按照接口实际结构定义匹配的Codable模型,先将返回数据解码为模型对象,再通过map提取所有子类型的名称字段赋值给选择器数据源,最后回到主线程刷新控件即可,修正后代码:
let decoder = JSONDecoder() if let jsonResponse = try? decoder.decode(Subtypes.self, from: data) { SubtypeList = jsonResponse.result self.subtypePickerData = SubtypeList.map{$0.Name} DispatchQueue.main.async { self.subtypePicker.reloadAllComponents() } }
提示:如果接口返回的字段名和代码中命名规范不一致,可以通过Codable的CodingKeys做字段映射,避免解码失败。
内容的提问来源于stack exchange,提问作者Mike Volmar
相关产品推荐
相关产品推荐

