在我的應用程式中,我試圖獲取下一個按鈕以繼續獲取新頁面。當我按下下一個 501 加載時,當我按下上一個 499 加載時。我知道這是因為comicNumber 設定為500,但是我無法讓它繼續運行(502,503 等)。
這是我的 api 呼叫
struct Comic: Codable {
var month: String
var num: Int
var link: String
var year: String
var news: String
var safe_title: String
var transcript: String
var alt: String
var img: String
var title: String
var day: String
}
enum ApiError: Error {
case dataIsNil
}
class ApiCall {
var comicNumber: Int
init(comicNumber: Int) {
self.comicNumber = comicNumber
}
func getComic(completion: @escaping (Result<Comic, Error>) -> ()) {
guard let url = URL(string: "https://xkcd.com/\(comicNumber)/info.0.json") else {return}
URLSession.shared.dataTask(with: url) { data, _, error in
if let error = error {
print(error)
completion(.failure(error))
return
}
guard let data = data else {
print("data is nil")
completion(.failure(ApiError.dataIsNil))
return
}
do {
let comic = try JSONDecoder().decode(Comic.self, from: data)
// print(comic)
DispatchQueue.main.async {
completion(.success(comic))
}
} catch {
print(error)
completion(.failure(error))
}
}
.resume()
}
func getNextComic(completion: @escaping (Result<Comic, Error>) -> ()) {
guard let url = URL(string: "https://xkcd.com/\(comicNumber)/info.0.json") else {return}
URLSession.shared.dataTask(with: url) { data, _, error in
if let error = error {
print(error)
completion(.failure(error))
return
}
guard let data = data else {
print("data is nil")
completion(.failure(ApiError.dataIsNil))
return
}
do {
let comic = try JSONDecoder().decode(Comic.self, from: data)
DispatchQueue.main.async {
completion(.success(comic))
}
} catch {
print(error)
completion(.failure(error))
}
}
.resume()
}
func getPrevComic(completion: @escaping (Result<Comic, Error>) -> ()) {
guard let url = URL(string: "https://xkcd.com/\(comicNumber)/info.0.json") else {return}
URLSession.shared.dataTask(with: url) { data, _, error in
if let error = error {
print(error)
completion(.failure(error))
return
}
guard let data = data else {
print("data is nil")
completion(.failure(ApiError.dataIsNil))
return
}
do {
let comic = try JSONDecoder().decode(Comic.self, from: data)
DispatchQueue.main.async {
completion(.success(comic))
}
} catch {
print(error)
completion(.failure(error))
}
}
.resume()
}
}
這是我的觀點
struct ComicContainer: View {
@State var comic: Comic?
@State var comicNumber = 500
var body: some View {
ZStack {
VStack {
NavigationLink(destination: ComicDetailView(), label: {
AsyncImage(url: URL(string: comic?.img ?? "Hello")) { image in
image
.resizable()
.scaledToFit()
} placeholder: {
Color.purple.opacity(0.1)
}
.padding()
})
.onAppear {
ApiCall(comicNumber: comicNumber).getComic{ result in
switch result {
case .success(let comic):
self.comic = comic
case .failure(let error):
print(error)
}
}
}
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
CustomButton {
ApiCall(comicNumber: comicNumber - 1).getPrevComic{ result in
switch result {
case .success(let comic):
self.comic = comic
print(comic.num)
case .failure(let error):
print(error)
}
}
} content: {
Text("Prev")
}
Spacer()
Text("Comic num: \(comic?.num ?? 0)")
.padding()
Spacer()
CustomButton {
ApiCall(comicNumber: comicNumber 1).getNextComic{ result in
switch result {
case .success(let comic):
self.comic = comic
print(comic.num)
case .failure(let error):
print(error)
}
}
} content: {
Text("Next")
}
}
}
.navigationBarTitle("\(comic?.title ?? "title")")
}
}
}
}
我試過這樣當你按下下一個或上一個按鈕時,comicNumber 會得到 1 或 - 1
ApiCall(comicNumber: comicNumber 1).getNextComic{
我也嘗試在 api 中使用 1 但它是一樣的。
guard let url = URL(string: "https://xkcd.com/\(comicNumber 1)/info.0.json") else {return}
有沒有人對我如何讓它作業或我做錯了什么有任何指導?我正在學習 Swift,非常感謝您的幫助<3
uj5u.com熱心網友回復:
comicNumber存盤在太多地方。在 SwiftUI 中,我們嘗試保持“單一事實來源”。將 ApiCall() 的實體保留為視圖的成員,以便 ComicNumber 保持更新:
struct ComicContainer: View {
@State var comic: Comic?
var api = ApiCall(comicNumber: 500)
var body: some View {
ZStack {
VStack {
NavigationLink(destination: ComicDetailView(), label: {
AsyncImage(url: URL(string: comic?.img ?? "Hello")) { image in
image
.resizable()
.scaledToFit()
} placeholder: {
Color.purple.opacity(0.1)
}
.padding()
})
.onAppear {
apiCall.getComic{ result in
switch result {
case .success(let comic):
self.comic = comic
case .failure(let error):
print(error)
}
}
}
.toolbar {
ToolbarItemGroup(placement: .bottomBar) {
CustomButton {
apiCall.getPrevComic{ result in
switch result {
case .success(let comic):
self.comic = comic
print(comic.num)
case .failure(let error):
print(error)
}
}
} content: {
Text("Prev")
}
Spacer()
Text("Comic num: \(comic?.num ?? 0)")
.padding()
Spacer()
CustomButton {
apiCall.getNextComic{ result in
switch result {
case .success(let comic):
self.comic = comic
print(comic.num)
case .failure(let error):
print(error)
}
}
} content: {
Text("Next")
}
}
}
.navigationBarTitle("\(comic?.title ?? "title")")
}
}
}
}
ApiCall并在視圖模型 ( )中處理comicNumber 的更新:
class ApiCall {
var comicNumber: Int
init(comicNumber: Int) {
self.comicNumber = comicNumber
}
func getComic(completion: @escaping (Result<Comic, Error>) -> ()) {
guard let url = URL(string: "https://xkcd.com/\(comicNumber)/info.0.json") else {return}
URLSession.shared.dataTask(with: url) { data, _, error in
if let error = error {
print(error)
completion(.failure(error))
return
}
guard let data = data else {
print("data is nil")
completion(.failure(ApiError.dataIsNil))
return
}
do {
let comic = try JSONDecoder().decode(Comic.self, from: data)
// print(comic)
DispatchQueue.main.async {
completion(.success(comic))
}
} catch {
print(error)
completion(.failure(error))
}
}
.resume()
}
func getNextComic(completion: @escaping (Result<Comic, Error>) -> ()) {
// this
comicNumber = 1
getComic(completion: completion)
}
func getPrevComic(completion: @escaping (Result<Comic, Error>) -> ()) {
// this
comicNumber -= 1
getComic(completion: completion)
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/446954.html
