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

SwiftUI实现API数据刷新按钮及自适应随机索引问题求助

SwiftUI 名言刷新功能优化与问题修复

需求与当前问题

我实现了一段SwiftUI代码,通过异步函数调用API获取名言列表并随机展示单条名言。现在需要:

  1. 实现刷新按钮用于测试(后续要做24小时定时刷新的"每日名言")
  2. 优化随机选取名言时的硬编码数组长度问题,让代码自适应数据规模

当前遇到的问题:

  • 预览和运行时看不到按钮
  • 尝试过两种刷新实现方式都失败:
    • 直接在按钮动作里用Task调用await loadData(),遇到异步函数与数据结构的相关错误
    • 改用布尔值切换控制展示,但按钮仍不显示

当前代码的核心问题分析

  1. 按钮无可见内容:Button的label闭包是空的,导致按钮无法被看到
  2. 状态变量定义错误:buttonPressed定义在body内部,不是@State变量,状态变化不会触发视图更新
  3. 随机数固定不变:randNum是let常量,只会在初始化时生成一次,刷新后不会重新随机选名言
  4. 硬编码数组范围:Int.random(in: 1..<1643)直接写死了数组长度,无法适配API返回数据的变化
  5. 视图逻辑混乱:注释代码和当前逻辑混杂,导致展示逻辑不清晰

优化后的完整代码

import SwiftUI

struct Quote: Identifiable, Codable {
    let id = UUID()
    var author: String?
    var text: String?
    
    enum CodingKeys: String, CodingKey {
        case author, text
    }
}

struct ContentView: View {
    @State private var quotes = [Quote]()
    @State private var isLoading = false
    @State private var showQuote = false
    
    // 自适应数组长度的随机索引计算属性
    private var randomQuoteIndex: Int? {
        guard !quotes.isEmpty else { return nil }
        return Int.random(in: 0..<quotes.count)
    }
    
    var body: some View {
        VStack(alignment: .leading, spacing: 16) {
            // 可见的刷新按钮
            Button(action: refreshQuote) {
                Text("刷新名言")
                    .padding(.vertical, 8)
                    .padding(.horizontal, 16)
            }
            .foregroundColor(.blue)
            .border(Color.black, width: 1)
            
            // 展示区域:加载状态/名言/默认提示
            if isLoading {
                Text("加载中...")
            } else if let index = randomQuoteIndex, showQuote {
                Text(quotes[index].text ?? "暂无名言内容")
                    .font(.title3)
                Text("—— \(quotes[index].author ?? "佚名")")
                    .foregroundColor(.blue)
                    .font(.caption)
            } else {
                Text("点击按钮获取今日名言")
                    .font(.title2)
            }
        }
        .padding()
        .task {
            await loadData()
            // 初始加载完成后自动展示名言
            showQuote = true
        }
    }
    
    // 刷新逻辑:重新加载数据并切换展示状态
    private func refreshQuote() {
        Task {
            isLoading = true
            await loadData()
            isLoading = false
            showQuote = true
        }
    }
    
    private func loadData() async {
        guard let url = URL(string: "https://type.fit/api/quotes") else {
            print("Invalid URL")
            return
        }
        
        do {
            let (data, _) = try await URLSession.shared.data(from: url)
            quotes = try JSONDecoder().decode([Quote].self, from: data)
        } catch {
            print("数据加载失败:\(error.localizedDescription)")
            quotes = []
        }
    }
}

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

关键优化说明

  • 修复按钮可见性:给Button添加了Text("刷新名言")的标签,按钮现在可以正常显示
  • 状态变量规范化:用@State管理quotes、isLoading、showQuote,确保状态变化触发视图更新
  • 自适应随机索引:用计算属性randomQuoteIndex根据当前quotes数组长度生成随机数,彻底解决硬编码问题
  • 简化刷新逻辑:refreshQuote函数统一处理加载状态、数据刷新和展示控制,异步调用loadData时用Task包裹,符合SwiftUI异步规范
  • 添加加载状态:增加isLoading变量,在数据加载时显示"加载中..."提示,提升用户体验
  • 边界情况处理:判断数组为空的情况,避免越界崩溃,同时给缺失的文本/作者设置默认值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 19:45:30