我正在尝试从其 ISBN 中获取一本书的详细信息。这是迄今为止我所拥有的一个可重复的示例。我希望在按下按钮时获取数据,但是我所拥有的不起作用。我还将为下面的请求包含一个数据模型。此外,我想在它获取数据时覆盖某种加载动画。
struct ContentView: View {
@State var name: String = ""
@State var author: String = ""
@State var total: String = ""
@State var code = "ISBN"
private func fetchBook(id identifier: String) async throws -> GoogleBook {
let url = URL(string: "https://www.googleapis.com/books/v1/volumes?q={\(identifier)}")
let (data, _) = try await URLSession.shared.data(from: url!)
return try! JSONDecoder().decode(GoogleBook.self, from: data)
}
var body: some View {
VStack {
Text("Name: \(name)")
Text("Author: \(author)")
Text("total: \(total)")
Button(action: {
code = "9780141375632"
Task {
do {
let fetchedBooks = try await fetchBook(id: code)
let book = fetchedBooks.items[0].volumeInfo
name = book.title
author = book.authors[0]
total = String(book.pageCount!)
} catch {
print(error.localizedDescription)
}
}
}, label: {
Rectangle()
.frame(width: 200, height: 100)
.foregroundColor(.blue)
})
}
}
}
import Foundation
// MARK: - GoogleBook
struct GoogleBook: Decodable {
let kind: String
let totalItems: Int
let items: [Item]
}
// MARK: - Item
struct Item: Decodable {
let kind: Kind
let id, etag: String
let selfLink: String
let volumeInfo: VolumeInfo
let saleInfo: SaleInfo
let accessInfo: AccessInfo
let searchInfo: SearchInfo
}
// MARK: - AccessInfo
struct AccessInfo: Decodable {
let country: Country
let viewability: Viewability
let embeddable, publicDomain: Bool
let textToSpeechPermission: TextToSpeechPermission
let epub, pdf: Epub
let webReaderLink: String
let accessViewStatus: AccessViewStatus
let quoteSharingAllowed: Bool
}
enum AccessViewStatus: String, Decodable {
case none = "NONE"
case sample = "SAMPLE"
}
enum Country: String, Decodable {
case countryIN = "IN"
}
// MARK: - Epub
struct Epub: Decodable {
let isAvailable: Bool
let acsTokenLink: String?
}
enum TextToSpeechPermission: String, Decodable {
case allowed = "ALLOWED"
case allowedForAccessibility = "ALLOWED_FOR_ACCESSIBILITY"
}
enum Viewability: String, Decodable {
case noPages = "NO_PAGES"
case partial = "PARTIAL"
}
enum Kind: String, Decodable {
case booksVolume = "books#volume"
}
// MARK: - SaleInfo
struct SaleInfo: Decodable {
let country: Country
let saleability: Saleability
let isEbook: Bool
let listPrice, retailPrice: SaleInfoListPrice?
let buyLink: String?
let offers: [Offer]?
}
// MARK: - SaleInfoListPrice
struct SaleInfoListPrice: Decodable {
let amount: Double
let currencyCode: CurrencyCode
}
enum CurrencyCode: String, Decodable {
case inr = "INR"
}
// MARK: - Offer
struct Offer: Decodable {
let finskyOfferType: Int
let listPrice, retailPrice: OfferListPrice
}
// MARK: - OfferListPrice
struct OfferListPrice: Decodable {
let amountInMicros: Int
let currencyCode: CurrencyCode
}
enum Saleability: String, Decodable {
case forSale = "FOR_SALE"
case notForSale = "NOT_FOR_SALE"
}
// MARK: - SearchInfo
struct SearchInfo: Decodable {
let textSnippet: String
}
// MARK: - VolumeInfo
struct VolumeInfo: Decodable {
let title: String
let authors: [String]
let publisher, publishedDate, volumeInfoDescription: String
let industryIdentifiers: [IndustryIdentifier]
let readingModes: ReadingModes
let pageCount: Int?
let printType: PrintType
let categories: [String]?
let averageRating: Double?
let ratingsCount: Int?
let maturityRating: MaturityRating
let allowAnonLogging: Bool
let contentVersion: String
let panelizationSummary: PanelizationSummary?
let imageLinks: ImageLinks
let language: Language
let previewLink: String
let infoLink: String
let canonicalVolumeLink: String
let subtitle: String?
let comicsContent: Bool?
let seriesInfo: SeriesInfo?
enum CodingKeys: String, CodingKey {
case title, authors, publisher, publishedDate
case volumeInfoDescription = "description"
case industryIdentifiers, readingModes, pageCount, printType, categories, averageRating, ratingsCount, maturityRating, allowAnonLogging, contentVersion, panelizationSummary, imageLinks, language, previewLink, infoLink, canonicalVolumeLink, subtitle, comicsContent, seriesInfo
}
}
// MARK: - ImageLinks
struct ImageLinks: Decodable {
let smallThumbnail, thumbnail: String
}
// MARK: - IndustryIdentifier
struct IndustryIdentifier: Decodable {
let type: TypeEnum
let identifier: String
}
enum TypeEnum: String, Decodable {
case isbn10 = "ISBN_10"
case isbn13 = "ISBN_13"
}
enum Language: String, Decodable {
case en = "en"
}
enum MaturityRating: String, Decodable {
case notMature = "NOT_MATURE"
}
// MARK: - PanelizationSummary
struct PanelizationSummary: Decodable {
let containsEpubBubbles, containsImageBubbles: Bool
let imageBubbleVersion: String?
}
enum PrintType: String, Decodable {
case book = "BOOK"
}
// MARK: - ReadingModes
struct ReadingModes: Decodable {
let text, image: Bool
}
// MARK: - SeriesInfo
struct SeriesInfo: Decodable {
let kind, shortSeriesBookTitle, bookDisplayNumber: String
let volumeSeries: [VolumeSery]
}
// MARK: - VolumeSery
struct VolumeSery: Decodable {
let seriesID, seriesBookType: String
let orderNumber: Int
let issue: [Issue]
enum CodingKeys: String, CodingKey {
case seriesID = "seriesId"
case seriesBookType, orderNumber, issue
}
}
// MARK: - Issue
struct Issue: Decodable {
let issueDisplayNumber: String
}