#ios #swift #swiftui #alamofire
Вопрос:
Я использую Alamofire в SwiftUI, чтобы получить игру со списком из https://api.rawg.io/api/games.
Затем я хочу получить подробную информацию об игре на основе их идентификатора в списке игр с https://api.rawg.io/api/games/{идентификатор}.
Но теперь идентификатор игры все еще статичен. Итак, мой вопрос в том, как запросить данные с идентификатором (из выбранного элемента в игре списка)?
Вот мой ApiServiceDetail.swift
(со статическим идентификатором: 3328)
import Foundation
import Alamofire
class ApiServiceDetail: ObservableObject {
@Published var gameDetail = DetailGame(id: 0, name: "", backgroundImage: "",
description: "", website: "" )
@Published var loading = false
private let apiKey = "?key=MY_KEY"
private let apiURLBase = "https://api.rawg.io/api/games/"
init() {
loading = true
loadDataByAlamofire(id: 3328)
}
private func loadDataByAlamofire(id: Int) {
AF.request("(apiURLBase)(id)(apiKey)")
.responseJSON { response in
switch response.result {
case .success:
print("Success Get Data")
guard let data = response.data else { return }
let detailGames = try! JSONDecoder().decode(DetailGame.self, from: data)
DispatchQueue.main.async {
self.gameDetail = detailGames
self.loading = false
}
case .failure:
print("Error Connect to Server")
}
}
}
}
DetailGame.swift
(Модель)
import Foundation
struct DetailGame: Codable, Identifiable {
let id: Int
let name, backgroundImage, description, website: String
enum CodingKeys: String, CodingKey {
case name, website, id
case backgroundImage = "background_image"
case description = "description_raw"
}
}
ContentView.swift
(для отображения списка игр и получения идентификатора игры)
import Foundation
import SwiftUI
struct ContentView: View {
@ObservedObject var apiService = ApiService()
var body: some View {
TabView {
NavigationView {
VStack {
if apiService.loading {
ProgressView()
} else {
List(apiService.games.results) { game in
NavigationLink(destination: GameDetail(idGame: game.id)) {
GameRow(game: game)
}
}
}
}
.navigationTitle("List Games")
}
.tabItem {
Image(systemName: "house")
Text("Home")
}.tag(1)
NavigationView {
About()
.navigationTitle("About")
}
.tabItem {
Image(systemName: "person.crop.circle")
Text("About")
}.tag(2)
}
}
}
GameDetail.swift
(Детальный Просмотр Игры)
import SwiftUI
import URLImage
import Alamofire
struct GameDetail: View {
@ObservedObject var apiServiceDetail = ApiServiceDetail()
var idGame: Int
var body: some View {
ScrollView {
VStack (alignment: .leading) {
URLImage(URL(string: "(apiServiceDetail.gameDetail.backgroundImage)")!) { image in
image
.resizable()
.aspectRatio(contentMode: .fill)
.border(Color.gray.opacity(0.5))
.offset(x: 0, y: 0)
.padding(.bottom, 0)
.frame(width: UIScreen.main.bounds.height/8*3, height: UIScreen.main.bounds.height/2)
}
Text("(apiServiceDetail.gameDetail.name)")
.font(.system(size: 25))
.bold()
Spacer()
Text("Website")
.bold()
Text("(apiServiceDetail.gameDetail.website)")
.foregroundColor(.blue)
.underline()
.onTapGesture {
UIApplication.shared.open(URL(string: "(apiServiceDetail.gameDetail.website)")!, options: [:])
}
Spacer(minLength: 10)
Text("Description")
.bold()
Text(apiServiceDetail.gameDetail.description)
}
}
.navigationBarTitle(Text(apiServiceDetail.gameDetail.name), displayMode: .inline)
.padding()
}
}
Комментарии:
1. Вы можете использовать
.onAppear
для запуска загрузки соответствующийid
, но вашему представлению потребуется обработать начальный случай, когда игровые данные не заполнены.2. Если у вас есть
Decodable
тип, используйтеresponseDecodable
. Выполнение этого вresponseJSON
избыточно, так как JSON уже был проанализирован один раз.