swift 正在尝试创建按钮/方法以刷新从API显示的数据(初学者)

noj0wjuj  于 2022-11-21  发布在  Swift
关注(0)|答案(1)|浏览(106)

我最近得到了一些使用异步函数调用API的代码,并显示从API中随机获取的一组信息。我现在正在研究一种刷新这些信息的方法。理想情况下,我希望它在24小时计时器上刷新,这样它就是一个“每日报价”,但目前我正尝试实现一个按钮来完成此操作,以便可以更频繁地刷新以进行测试和调试。目前我想尝试和修复的另一件事是,在代码中,我已经在挑选随机信息集时硬编码了数据结构的长度,并希望这对不同的数据结构大小更有适应性。这个项目的所有代码都可以在下面找到

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 var quotes = [Quote]()
    //var buttonPressed = true
    //var numQuotes = [Int()]
    
    let randNum = Int.random(in: 1..<1643)
    
    var body: some View {
    
        var buttonPressed = Bool()
        
        VStack(alignment: .leading) {
            /*Text("Quote of the Day")
            Button(action: {
                Task{
                    await loadData()
                }
                
            }, label: {
                if quotes.count > 0 {
                    Text(quotes[randNum].text ?? "no text")
                    Text(quotes[randNum].author ?? "no author").foregroundColor(.blue)
                }
            })
            .foregroundColor(.blue)*/
            Button(action: {
                buttonPressed.toggle()
            }) {
                //buttonPressed
            }
            .foregroundColor(.blue)
            .border(Color.black, width: 1)
            if quotes.count > 0 && buttonPressed == true{
                Text(quotes[randNum].text ?? "no text")
                Text(quotes[randNum].author ?? "no author").foregroundColor(.blue)
                }else{
                    Text("Quote of the Day")
                }
            }.task{
                await loadData()
                
        }
    }

    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)
            //print("The count is",quotes.count)
            //numQuotes = quotes.count
            //print("numQuotes is",numQuotes)
            //print(quotes)
            //print(quotes[0].text ?? "Error")
        } catch {
            print(error)
            }
        }
    }

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

Xcode目前没有抛出任何错误,但在预览或运行构建时看不到该按钮。我可能需要将一些代码移到不同的文件中,这可能是导致问题的原因,但我希望能有更多的人来看看我是否可以改进。
我尝试了多种方法来实现刷新API数据的按钮,但是遇到了很多问题。
我尝试的第一个解决方案是将按钮操作设置为“await LoadData()”任务,但在各种情况下都失败了。
我得到的主要错误是关于异步函数和数据结构不可变。
我已经设置了按钮动作来切换布尔值,如果布尔值为“真”,则显示数据。
我对swift相对较新,可能会错过一些东西。提前谢谢你

dw1jzc5e

dw1jzc5e1#

尝试这种方法,你设置随机报价显示在一个按钮点击。然后显示当天的报价,而不是每次重新加载数据。
您应该阅读Swift的基本知识,网址为:https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html并做一些练习来了解Swift。
另外你还需要做一些教程,比如:https://developer.apple.com/tutorials/swiftui/

struct ContentView: View {
    @State var quotes = [Quote]()
    @State var randNum = 0
    
    var body: some View {
        VStack(alignment: .leading, spacing: 33) {
            Text("Quote of the Day").foregroundColor(.red)
            
            if quotes.count > 0 {
                Text(quotes[randNum].text ?? "no text").foregroundColor(.black)
                Text(quotes[randNum].author ?? "no author").foregroundColor(.blue)
            } else {
                ProgressView()
            }
            
            Button("New quote") {
               randNum = Int.random(in: 0..<quotes.count)
            }.buttonStyle(.bordered)
        }
        .task {
            await loadData()
            randNum = Int.random(in: 0..<quotes.count)
        }
    }
    
    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)
        }
    }
}

编辑-1:
如果你真的想在每次点击按钮时重新加载数据,没问题,就用这个:

Button("New quote") {
     Task {
         await loadData()
         randNum = Int.random(in: 0..<quotes.count)
     }
 }.buttonStyle(.bordered)

相关问题