如何从JSON响应获取价格数据并保存至UserDefaults?附相关代码
实现JSON解析与UserDefaults存储完整流程
首先,先把你的Price类的NSCoding实现补全——毕竟要存到UserDefaults,必须实现编码和解码方法:
class Price : NSObject, NSCoding { var id, id_service: Int var nationality: String var price: Int var createdAt: String? var updatedAt: String? // 普通初始化方法,补全可选参数 init(id: Int, id_service: Int, nationality: String, price: Int, createdAt: String? = nil, updatedAt: String? = nil) { self.id = id self.id_service = id_service self.nationality = nationality self.price = price self.createdAt = createdAt self.updatedAt = updatedAt } // NSCoding 解码方法,从归档数据恢复对象 required init?(coder: NSCoder) { self.id = coder.decodeInteger(forKey: "id") self.id_service = coder.decodeInteger(forKey: "id_service") self.nationality = coder.decodeObject(forKey: "nationality") as? String ?? "" self.price = coder.decodeInteger(forKey: "price") self.createdAt = coder.decodeObject(forKey: "createdAt") as? String self.updatedAt = coder.decodeObject(forKey: "updatedAt") as? String } // NSCoding 编码方法,把对象转成归档数据 func encode(with coder: NSCoder) { coder.encode(id, forKey: "id") coder.encode(id_service, forKey: "id_service") coder.encode(nationality, forKey: "nationality") coder.encode(price, forKey: "price") coder.encode(createdAt, forKey: "createdAt") coder.encode(updatedAt, forKey: "updatedAt") } }
接下来我们一步步完成从JSON响应到存储的完整流程:
1. 解析JSON响应为Prices结构体数组
假设你的接口返回的是Prices对象的数组,解析代码可以这么写:
func parsePrices(from data: Data) -> [Prices]? { do { let decoder = JSONDecoder() // 如果接口返回的JSON是蛇形命名(比如created_at),一定要加这个配置,不然解析会失败 decoder.keyDecodingStrategy = .convertFromSnakeCase let pricesArray = try decoder.decode([Prices].self, from: data) return pricesArray } catch { print("JSON解析失败:\(error.localizedDescription)") return nil } }
2. 将结构体转成可归档的Price类实例
UserDefaults不能直接存结构体,所以需要把解析出来的Prices结构体转成我们写的Price类:
func convertToPriceInstances(_ prices: [Prices]) -> [Price] { return prices.map { priceStruct in Price(id: priceStruct.id, id_service: priceStruct.id_service, nationality: priceStruct.nationality, price: priceStruct.price, createdAt: priceStruct.createdAt, updatedAt: priceStruct.updatedAt) } }
3. 把Price实例存入UserDefaults
自定义对象需要先转成Data格式,才能存入UserDefaults:
func savePricesToUserDefaults(_ prices: [Price]) { do { let data = try NSKeyedArchiver.archivedData(withRootObject: prices, requiringSecureCoding: false) UserDefaults.standard.set(data, forKey: "savedPrices") // iOS12+之后synchronize()不是必须的,但加上也不影响 UserDefaults.standard.synchronize() } catch { print("存储到UserDefaults失败:\(error.localizedDescription)") } }
4. 从UserDefaults读取存储的价格数据
把存进去的Data再转回到Price数组:
func loadPricesFromUserDefaults() -> [Price]? { guard let data = UserDefaults.standard.data(forKey: "savedPrices") else { return nil } do { guard let prices = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? [Price] else { return nil } return prices } catch { print("从UserDefaults读取失败:\(error.localizedDescription)") return nil } }
完整调用示例
假设你已经从接口拿到了JSON数据data,可以这样串联整个流程:
// 解析JSON if let pricesStructArray = parsePrices(from: data) { // 转成可归档的类实例 let priceInstances = convertToPriceInstances(pricesStructArray) // 存入UserDefaults savePricesToUserDefaults(priceInstances) // 测试读取 if let loadedPrices = loadPricesFromUserDefaults() { print("成功读取到\(loadedPrices.count)条价格数据") for price in loadedPrices { print("国籍:\(price.nationality),价格:\(price.price)") } } }
最后提几个小注意点:
- 如果接口返回的JSON字段是蛇形命名(比如
created_at),decoder.keyDecodingStrategy = .convertFromSnakeCase这个配置一定要加,不然解析会匹配不上字段 - 如果需要更安全的存储,可以让
Price类遵循NSSecureCoding,并修改编码解码方法 - UserDefaults只适合存储少量数据,如果你的价格数据量很大,建议改用Core Data或者其他本地存储方案
内容的提问来源于stack exchange,提问作者lamatat
相关产品推荐
相关产品推荐

