0

I am fairly new to Swift and SwiftUI, can anyone help me understand why when I try to call a specific tv show using the fecthUserSeries function, nothing appears?

Here are the endpoints

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
}

Here are all the functions:

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
    }
}

Finally, here is where I am calling the function. As you can see, I am calling a show with index = 1 (the fetchSeries function is a separate one that retrieves all shows from each page of the database)

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
  • 2
    Welcome to Stack Overflow. You pasted a lot of code and most users will not be bothered to read it all. I recommend you use the breakpoints feature on Xcode to determine what lines of code are being hit and the print() function to print the values of your variables to see if they are being set. Narrow the error down and show us the problematic code, not the entire project. Commented Aug 5, 2020 at 3:20

1 Answer 1

1

in APIStore class try this:

func fetchUserSeries(seriesID: Int)

to

func fetchUserSeries(with seriesID: Int) {

add the "with" as external param

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.