SwiftUI报错:init(_:)要求OneCall.HourlyResponse遵循StringProtocol
报错根因
- 触发编译报错的直接原因:SwiftUI的
Text组件初始化要求传入值符合StringProtocol(即字符串类型),但你传入的weather.hourly是自定义的OneCall.HourlyResponse结构体类型,系统无法自动将结构体转换为字符串,因此抛出类型不匹配错误。 - 底层逻辑问题:你的数据模型定义和OpenWeatherMap OneCall API 1.0的实际返回结构完全不符:接口返回的
hourly字段是逐小时天气数据的数组,不是单个自定义对象;同时你定义的HourlyResponse内部字段也和接口返回字段不匹配,即使绕过当前编译报错,后续接口数据解码也会失败。
修复方案
1. 修正数据模型定义
按照OpenWeatherMap接口的实际返回结构调整模型,注意hourly是数组类型,单条逐小时数据定义为可识别结构,方便ForEach遍历:
struct OneCall: Decodable{ let lat, lon: Double let timezone : String let timezone_offset : Int let current: CurrentResponse // hourly为逐小时数据数组,接口默认返回48条数据 let hourly: [HourlyEntry] // 单条逐小时数据结构,遵循Identifiable方便列表遍历 struct HourlyEntry: Decodable, Identifiable { // 本地使用的唯一ID,不参与接口解码 let id = UUID() // 接口返回的时间戳 let dt: TimeInterval // 对应小时的温度 let temp: Double // 天气状况数组 let weather: [WeatherMeta] // 如需用到降水概率pop、体感温度feels_like等字段,可对照接口文档自行补充 } struct WeatherMeta: Decodable { let main: String let description: String let icon: String } // 其余原有子结构体(如CurrentResponse)保持原有定义即可 }
2. 修正视图层遍历逻辑
不要写死遍历区间,直接遍历解码后的逐小时数据数组,传入Text的必须是明确的字符串值:
ScrollView(.horizontal){ HStack(spacing: 12) { // 取前25条逐小时数据遍历 ForEach(Array(weather.hourly.prefix(25))) { hourItem in VStack(spacing: 8){ // 示例:显示格式化后的小时时间 Text(formatTimestampToHour(hourItem.dt)) .font(.caption) // 示例:显示整数温度,拼接摄氏度符号 Text("\(Int(hourItem.temp))°") .bold() .font(.subheadline) } .frame(width: 60) } } } // 时间戳转小时字符串的辅助方法 func formatTimestampToHour(_ timestamp: TimeInterval) -> String { let date = Date(timeIntervalSince1970: timestamp) let formatter = DateFormatter() formatter.dateFormat = "HH:mm" return formatter.string(from: date) }
临时绕过方案:如果只是想快速消除当前编译报错不考虑解码逻辑,可以把
Text(weather.hourly)改成Text(weather.hourly.hourly),直接传入结构体内部的字符串属性,但这种方式不符合接口实际结构,无法正常解析接口返回数据,仅做临时测试用。
内容的提问来源于stack exchange,提问作者Aadish123
相关产品推荐
相关产品推荐

