Вызов данных API Swift / SwiftUI - PullRequest
       101

Вызов данных API Swift / SwiftUI

0 голосов
/ 05 августа 2020

Я новичок в Swift и SwiftUI, может ли кто-нибудь помочь мне понять, почему, когда я пытаюсь вызвать определенное c телешоу с помощью функции fecthUserSeries, ничего не появляется?

Вот конечные точки

import UIKit

struct AppData {
    static let baseUrl = "https://api.tvmaze.com"
    static let search = "/search/shows"
    static let show = "/show/"
    static let shows = "/shows/"
    static let episodes = "/episodes"
    static let season = "/seasons"
    static let cast = "/cast"
    static let crew = "/crew"
    static let placeholderUrl = "http://via.placeholder.com/350/ffffff/000000?text=Image+Not+found"
    static let dateFormat = "dd MMM yyyy"
    static let dateFormatApi = "yyyy-MM-dd"
    
}


enum AppError : Error {
    case invalidFormat
}

Вот все функции:

import SwiftUI
import Combine

enum APIType {
    case listSeries
    case listseasons
    case listEpisodes
    case listCast
    case listCrew
}

class APIStore: ObservableObject {
    
    @Published var serieses: [Series] = []
    @Published var seasons: [Season] = []
    @Published var episodes: [Episode] = []
    @Published var casts: [CastCrew] = []
    @Published var crews: [CastCrew] = []

    
    
    init() {
        serieses = []
        seasons = []
        episodes = []
        casts = []
        crews = []
    }
    
    func fetchSeries(pageNumber: Int = 1)  {
        
        let params = [
            ("page", String(pageNumber))
        ]
        ApiMapper().callAPI(withPath: AppData.show, params: params, andMappingModel: [Series].self) { [weak self] (result) in
            switch(result) {
            case .success(let serieses):
                DispatchQueue.main.async {
                    self?.serieses = serieses
                }
            case .failure(_):
                break
            }
        }
    }
    
    
    func searchSeries(searchString: String)  {
           
           let params = [
               ("q", searchString)
           ]
           ApiMapper().callAPI(withPath: AppData.search, params: params, andMappingModel: [SearchResult].self) { [weak self] (result) in
               switch(result) {
               case .success(let searchResult):
                   DispatchQueue.main.async {
                    self?.serieses = searchResult.compactMap({$0.series})
                   }
               case .failure(_):
                   break
               }
           }
       }
    
    
    func fetchSeason(with seriesID: Int)  {
        
        let path = "\(AppData.shows)\(seriesID)\(AppData.season)"
        ApiMapper().callAPI(withPath: path, params: [], andMappingModel: [Season].self) { [weak self] (result) in
            switch(result) {
            case .success(let seasons):
                DispatchQueue.main.async {
                    self?.seasons = seasons
                }
            case .failure(_):
                break
            }
        }
    }
    
    func fetchEpisodes(with seriesID: Int)  {
        let path = "\(AppData.shows)\(seriesID)\(AppData.episodes)"
        
        ApiMapper().callAPI(withPath: path, params: [], andMappingModel: [Episode].self) { [weak self] (result) in
            switch(result) {
            case .success(let episodes):
                DispatchQueue.main.async {
                    self?.episodes = episodes
                }
            case .failure(_):
                break
            }
        }
    }
    
    func fetchCasts(with seriesID: Int)  {
         let path = "\(AppData.shows)\(seriesID)\(AppData.cast)"

         ApiMapper().callAPI(withPath: path, params: [], andMappingModel: [CastCrew].self) { [weak self] (result) in
             switch(result) {
             case .success(let casts):
                 DispatchQueue.main.async {
                     self?.casts = casts
                 }
             case .failure(_):
                 break
             }
         }
     }
    
    func fetchCrews(with seriesID: Int)  {
         let path = "\(AppData.shows)\(seriesID)\(AppData.crew)"

         ApiMapper().callAPI(withPath: path, params: [], andMappingModel: [CastCrew].self) { [weak self] (result) in
             switch(result) {
             case .success(let casts):
                 DispatchQueue.main.async {
                     self?.crews = casts
                 }
             case .failure(_):
                 break
             }
         }
     }

    func fetchUserSeries(seriesID: Int)  {
        let path = "\(AppData.shows)\(seriesID)"
        
        ApiMapper().callAPI(withPath: path, params: [], andMappingModel: [Series].self) { [weak self] (result) in
            switch(result) {
            case .success(let userSeries):
                DispatchQueue.main.async {
                    self?.serieses = userSeries
                }
            case .failure(_):
                print("Error")
                break
            }
        }
    }
}
import UIKit

class ApiMapper {
    
    //MARK: Api Calls
    
    func callAPI<T: Codable>(withPath pathString: String, params : [(String, String)], andMappingModel model: T.Type, callback: @escaping (Result<T, Error>) -> Void ) {
        
        if let url = self.generateURL(withPath: pathString , andParams: params) {
            let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
                do {
                    let jsonDecoder = JSONDecoder()
                    let responseModel = try jsonDecoder.decode(model, from: data!)
                    callback(Result.success(responseModel))
                } catch {
                    callback(Result.failure(error))
                }
            }
            task.resume()
        } else {
            callback(Result.failure(URLError(.badURL)))
        }
    }
    
    //MARK: helper methods
    
    private func generateURL(withPath path: String, andParams params: [(String, String)]) -> URL? {
        
        guard var urlComp = URLComponents(string: AppData.baseUrl) else {return nil}
        urlComp.queryItems = [URLQueryItem]()
        for param in params {
            urlComp.queryItems?.append(URLQueryItem(name: param.0, value: param.1))
        }
        guard var  url = urlComp.url else {return nil}
        url = url.appendingPathComponent(path)
        return url
    }
}

Наконец, вот где я вызываю функцию. Как видите, я вызываю шоу с index = 1 (функция fetchSeries - это отдельная функция, которая извлекает все шоу с каждой страницы базы данных)

import SDWebImageSwiftUI

struct HomeView: View {
    
    @ObservedObject var apiStore  = APIStore()
    @State private var searchString = ""
    @State private var pageNumber = 1
    @State var selectedSeason: Int
//    var seriesID: [Int] = [178, 31, 555, 1855, 263]
    var seriesID: Int = 1
    
    init(selectedSeason: Int) {
        UITableView.appearance().separatorStyle = .none
        _selectedSeason = State(initialValue: selectedSeason)
    }
    
    var body: some View {
        NavigationView() {
            VStack {
                TextField("Search", text: $searchString, onEditingChanged: { status in
                    if !status && self.searchString != "" {
                        self.apiStore.searchSeries(searchString: self.searchString)
                        self.pageNumber = 1
                    } else if !status && self.searchString == "" {
                        self.apiStore.fetchSeries(pageNumber: self.pageNumber)
                    }
                })
                    .padding(.all, 10.0)
                    .textFieldStyle(RoundedBorderTextFieldStyle())
                List{
                    ForEach(self.apiStore.serieses) { series in
                        SeriesCell(series : self.apiStore.serieses[0], selectedSeason: self.$selectedSeason)
                            .onAppear {
//                                ForEach(self.seriesID.) { seriesID in
//                                if self.seriesID.contains(where: {$0 == series.id}){
//                                self.apiStore.fetchUserSeries(with: series.id ?? 0)
//                                }
                                self.apiStore.fetchUserSeries(with: self.seriesID)
                                
                                if series.id == self.apiStore.serieses.last?.id {
                                    self.pageNumber += 1
                                    self.apiStore.fetchSeries(pageNumber: self.pageNumber)

                                }
                        }
                    }
                }
                .navigationBarTitle("Shows", displayMode: .inline)
                .onAppear {
                    self.searchString == "" ? self.apiStore.fetchSeries() : self.apiStore.searchSeries(searchString: self.searchString)
//                    self.apiStore.fetchUserSeries()

//                    self.searchString == "" ? self.apiStore.fetchSeries() : self.apiStore.searchSeries(searchString: self.searchString)
                }
            }
        }
    }
}


struct SeriesCell: View {
    
    var series: Series
    @Binding var selectedSeason: Int
    
    var body: some View {
        NavigationLink(destination: DetailsView(series: series, selectedSeason: selectedSeason)) {
            ZStack(alignment: .topTrailing) {
                VStack(alignment: .center) {
                    WebImage(url: URL(string: (series.image?.original ?? "")))
                        .placeholder{Image(systemName: "camera")}
                        .resizable()
                        .scaledToFit()
                        .frame(minWidth: UIScreen.main.bounds.width - 60, minHeight:(UIScreen.main.bounds.width - 60))
                    HStack {
                        Text(String(series.name ?? ""))
                            .bold()
                            .multilineTextAlignment(.center)
                            .font(.title)
                            .padding(10)
                        
                      Image(systemName: "plus")
                        .onTapGesture {
                            
                        }
                    }
                }
                
                ZStack(alignment: .center) {
                    Image(systemName: "star.fill")
                        .resizable()
                        .scaledToFit()
                        .frame(width: 50, height: 50, alignment: .center)
                        .foregroundColor(Color.yellow)
                        .padding()
                    Text(String.localizedStringWithFormat("%.1f", series.rating?.average ?? 0))
                        .font(.system(size: 11))
                    .bold()
                }
            }
            .background(Color.white)
            .cornerRadius(6)
            .shadow(radius: 5)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        
        let content = HomeView(selectedSeason: 1)
        content.apiStore.serieses = SampleAPIResult.getDummySeries()
        return content
//            .previewDevice("iPhone 7")
    }
}


```

1 Ответ

0 голосов
/ 05 августа 2020

в классе APIStore попробуйте следующее:

fun c fetchUserSeries (seriesID: ​​Int)

to

fun c fetchUserSeries (with seriesID: ​​Int) {

добавить "with" как внешний параметр

...