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

如何从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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:20:09