代码本质上应该允许用户输入用户名、获取相关统计数据并将其显示在 UI 中。终端数据显示通过打印 JSON 已成功检索 API。
上下文:该 API 来自一款名为 Beyond All Reason 的游戏。
主要问题是我无法获取代码来解释结果并显示搜索到的用户玩过多少游戏,或与此相关的任何其他统计数据。正如你所看到的,我尝试在我的代码中实现 winCount。
import SwiftUI
struct User: Codable {
let id: Int
let username: String
}
struct UserStatsView: View {
@State private var searchText: String = ""
@StateObject private var viewModel = UserStatsViewModel()
var body: some View {
VStack {
TextField("Enter username", text: $searchText)
.padding()
.textFieldStyle(RoundedBorderTextFieldStyle())
.autocapitalization(.none)
Button(action: {
Task {
await viewModel.loadStats(for: searchText)
}
}) {
Text("Load Stats")
}
.padding()
if viewModel.isLoading {
ProgressView("Loading Stats...")
} else if viewModel.dataReceived {
Text("Data Received!")
if let totalGames = viewModel.totalGames {
Text("Total Games: \(totalGames)")
} else {
Text("Total Games: N/A")
}
if let winsCount = viewModel.winsCount {
Text("Number of Wins: \(winsCount)")
} else {
Text("Number of Wins: N/A")
}
}
}
.padding()
}
}
@MainActor
class UserStatsViewModel: ObservableObject {
@Published var isLoading: Bool = false
@Published var dataReceived: Bool = false
@Published var totalGames: Int?
@Published var winsCount: Int?
@MainActor
func loadStats(for username: String) async {
isLoading = true
dataReceived = false
guard let url = URL(string: "https://api.bar-rts.com/cached-users") else {
// Handle invalid URL
return
}
do {
let (data, _) = try await URLSession.shared.data(from: url)
let usersList = try JSONDecoder().decode([User].self, from: data)
if let user = usersList.first(where: { $0.username == username }) {
let userId = user.id
await fetchMatches(for: userId, username: username)
}
} catch {
print("Error: \(error)")
// Handle error
}
}
@MainActor
private func fetchMatches(for userId: Int, username: String) async {
guard var urlComponents = URLComponents(string: "https://api.bar-rts.com/replays") else {
// Handle invalid URL
return
}
let queryItems = [
URLQueryItem(name: "page", value: "1"),
URLQueryItem(name: "hasBots", value: "false"),
URLQueryItem(name: "endedNormally", value: "true"),
URLQueryItem(name: "preset", value: "team"),
URLQueryItem(name: "players", value: username),
URLQueryItem(name: "date", value: "2020-01-01"),
URLQueryItem(name: "date", value: "2024-06-30")
]
urlComponents.queryItems = queryItems
guard let url = urlComponents.url else {
// Handle invalid URL
return
}
do {
let (data, _) = try await URLSession.shared.data(from: url)
// Print the JSON data received
if let jsonString = String(data: data, encoding: .utf8) {
print("Received JSON data: \(jsonString)")
}
// Decode the JSON data as usual
let response = try JSONDecoder().decode(MatchDataResponse.self, from: data)
let matches = response.data
self.totalGames = matches.count
self.winsCount = matches.filter { $0.allyTeams.contains { $0.winningTeam } }.count
self.isLoading = false
self.dataReceived = true
} catch {
print("Error: \(error)")
// Handle error
}
}
}
import Foundation
// Structures for representing the JSON data
// Top-level structure representing the entire JSON data
struct MatchDataResponse: Codable {
let totalResults: Int
let page: Int
let limit: Int
let data: [MatchData]
}
struct MatchData: Codable {
let id: String
let startTime: Date
let durationMs: Double // Ensure this property is defined as Double
let map: Map
let allyTeams: [AllyTeam]
private enum CodingKeys: String, CodingKey {
case id, startTime, durationMs, map = "Map", allyTeams = "AllyTeams"
}
}
// Structure representing the map information
struct Map: Codable {
let fileName: String
let scriptName: String
}
// Structure representing ally team data
struct AllyTeam: Codable {
let winningTeam: Bool
let players: [Player]
let AIs: [AI] // Assuming there could be AI players
private enum CodingKeys: String, CodingKey {
case winningTeam, players = "Players", AIs
}
}
// Structure representing player data
struct Player: Codable {
let name: String
}
// Structure representing AI player data
struct AI: Codable {
// AI properties if any, not available in the provided JSON snippet
}
struct ContentView: View {
var body: some View {
UserStatsView()
}
}
有一个
DecodingError
:
错误:typeMismatch(Swift.Double,Swift.DecodingError.Context(codingPath:[CodingKeys(stringValue:“数据”,intValue:nil),_JSONKey(stringValue:“索引0”,intValue:0),CodingKeys(stringValue:“ startTime", intValue: nil)], debugDescription: "预期解码 Double 但发现了一个字符串。",underlyingError: nil))
startTime
是表示 ISO8601 日期的字符串。解码后的 Date
的默认 JSON 类型是 Double
,一个 UNIX 时间戳,这就是错误消息的内容。
将
startTime
解码为 String
或应用自定义日期解码策略。不幸的是,标准 .iso8601
不起作用,因为 ISO 日期字符串包含小数秒。
或者,如果您对日期不感兴趣,请删除结构中的
startTime
。不需要解码所有密钥。