Запросите данные Alamofire SwiftUI с параметром

#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 уже был проанализирован один раз.