Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • 第 12 章:图表与数据源整合

第 12 章:图表与数据源整合

从 API 获取数据(URLSession、async/await)

概述

在 SwiftUI 图表开发中,动态数据通常来自远程 API。本章将介绍如何使用 Swift 的 URLSession 和 async/await 语法从网络获取数据,并将其绑定到图表。

核心步骤

1. 定义数据模型

struct ChartData: Codable, Identifiable {
    let id: UUID
    let date: Date
    let value: Double
}

2. 创建异步数据加载器

class DataLoader: ObservableObject {
    @Published var dataPoints: [ChartData] = []
    @Published var isLoading = false
    @Published var error: Error?

    func loadData(from url: URL) async {
        isLoading = true
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            let decodedData = try JSONDecoder().decode([ChartData].self, from: data)
            DispatchQueue.main.async {
                self.dataPoints = decodedData
                self.isLoading = false
            }
        } catch {
            DispatchQueue.main.async {
                self.error = error
                self.isLoading = false
            }
        }
    }
}

3. 在 SwiftUI 视图中集成

struct ChartView: View {
    @StateObject private var loader = DataLoader()
    let apiURL = URL(string: "https://api.example.com/data")!

    var body: some View {
        VStack {
            if loader.isLoading {
                ProgressView()
            } else if let error = loader.error {
                ErrorView(error: error)
            } else {
                Chart(loader.dataPoints) { item in
                    LineMark(
                        x: .value("Date", item.date),
                        y: .value("Value", item.value)
                    )
                }
            }
        }
        .task {
            await loader.loadData(from: apiURL)
        }
    }
}

关键技术与注意事项

  1. async/await 最佳实践:

    • 使用 Task 包装异步调用
    • 在主线程更新 UI(通过 DispatchQueue.main)
    • 正确处理取消操作
  2. 错误处理:

    • 网络请求错误
    • JSON 解析错误
    • 空数据状态
  3. 性能优化:

    • 实现数据缓存(URLCache)
    • 节流频繁请求
    • 后台线程处理复杂数据
  4. 测试技巧:

    // 测试用例示例
    func testDataLoading() async throws {
        let testData = [ChartData(id: UUID(), date: Date(), value: 42)]
        let mockLoader = MockDataLoader(response: testData)
        let viewModel = ChartViewModel(loader: mockLoader)
        
        await viewModel.loadData()
        XCTAssertEqual(viewModel.dataPoints.count, 1)
    }
    

完整示例:天气数据 API 集成

// 扩展数据模型
struct WeatherData: Codable {
    let temperature: Double
    let humidity: Double
    let timestamp: Date
}

// 扩展数据加载器
extension DataLoader {
    func loadWeatherData() async {
        let weatherURL = URL(string: "https://weatherapi.com/forecast")!
        await loadData(from: weatherURL)
    }
}

常见问题解决方案

  1. 证书问题:在 Info.plist 中添加 NSAppTransportSecurity 配置
  2. 日期格式:自定义 JSONDecoder 的日期解码策略
    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .iso8601
    
  3. 大数据集:实现分页加载或数据采样

提示:对于生产环境应用,建议添加请求重试机制和网络状态监测功能。

Last Updated:: 5/18/25, 10:44 AM