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

SwiftUI无法从嵌套数组URL获取数据并填充列表求助

问题排查与代码修正

核心问题分析

  • 解码逻辑错误:目标JSON的根结构是包含lands数组的对象,而非直接的RideTime数组,原代码直接解码[RideTime].self完全不符合JSON结构,导致数据无法解析。
  • 数据类型不匹配:JSON中is_open是布尔值(true/false),wait_time是整数(如10),但结构体中错误定义为String类型,解码时会失败。
  • 数据收集缺失:即使解码正确,原代码也没有从lands数组中提取嵌套的rides数据到展示列表。
  • 缺少版权链接展示:未实现要求的"Powered by Queue-Times.com"链接。

修正后的完整代码

import SwiftUI

// 根结构:匹配JSON的顶层结构
struct Wrapper: Decodable {
    let lands: [Land]
}

// 区域结构:符合Identifiable协议,字段类型匹配JSON
struct Land: Decodable, Identifiable {
    let id: Int
    let name: String
    let rides: [RideTime]
}

// 游乐设施等待时间:修正数据类型,匹配JSON字段
struct RideTime: Decodable, Identifiable {
    let id: Int
    let name: String
    let is_open: Bool
    let wait_time: Int
}

struct ContentView: View {
    @State private var lands = [Land]()
    
    var body: some View {
        NavigationStack {
            // 按区域分组展示游乐设施
            List(lands) { land in
                Section(header: Text(land.name)) {
                    ForEach(land.rides) { ride in
                        VStack(alignment: .leading) {
                            Text(ride.name)
                                .font(.headline)
                            // 根据开放状态展示不同文本
                            Text(ride.is_open ? "\(ride.wait_time) mins" : "Closed")
                                .font(.body)
                                .foregroundColor(ride.is_open ? .primary : .red)
                        }
                    }
                }
            }
            .navigationTitle("Ride Wait Times")
            .task {
                await fetchData()
            }
            // 添加底部版权链接
            .toolbar {
                ToolbarItem(placement: .bottomBar) {
                    Link("Powered by Queue-Times.com", destination: URL(string: "https://queue-times.com/en-US")!)
                        .font(.caption)
                }
            }
        }
    }
    
    func fetchData() async {
        guard let url = URL(string: "https://queue-times.com/parks/16/queue_times.json") else {
            print("无效URL")
            return
        }
        
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            // 正确解码根结构Wrapper
            let decodedWrapper = try JSONDecoder().decode(Wrapper.self, from: data)
            lands = decodedWrapper.lands
        } catch {
            print("解码失败:\(error.localizedDescription)")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

关键改动说明

  1. 修正数据类型:将RideTime中的is_open改为Bool,wait_time改为Int,完全匹配JSON返回的字段类型,避免解码失败。
  2. 修复解码逻辑:先解码Wrapper类型获取完整的lands数组,再通过List+Section按区域分组展示游乐设施,贴合数据的层级结构。
  3. 优化展示逻辑:根据is_open状态显示不同文本和颜色,未开放时标注红色"Closed",提升用户体验。
  4. 添加版权链接:在底部工具栏中加入要求的跳转链接,使用Link组件实现功能。
  5. 调试友好化:将try?改为try并捕获具体错误信息,便于排查解码问题。

内容的提问来源于stack exchange,提问作者hackanaut

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 11:47:45