调用API数据Swift/SwiftUI



我是Swift和SwiftUI的新手,有人能帮助我理解为什么当我尝试使用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
}
}

最后,这里是我调用函数的地方。正如您所看到的,我正在调用索引为1的show(fetchSeries函数是一个单独的函数,它从数据库的每个页面检索所有show(

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

```

在APIStore类中尝试这个:

func fetchUserSeries(seriesID:Int(

func fetchUserSeries(带seriesID:Int({

添加";用";作为外部参数

最新更新