在斯威夫特还是新的。我已经搜索了很多关于这个主题的类似问题,但由于某种原因,我仍然无法确定问题出在我的结构是如何构建的,或者我做错了什么。谢谢你的帮助!
我在swift应用程序中使用newswatcher api,获取的数据如下所示:
{
"status": "ok",
"total_hits": 10000,
"page": 1,
"total_pages": 10000,
"page_size": 1,
"articles": [
{
"title": "Pizza Pizza has teamed up with Mattel for the ultimate game night combo",
"author": null,
"published_date": "2022-03-18 20:34:17",
"published_date_precision": "full",
"link": "https://dailyhive.com/vancouver/pizza-pizza-mattel-canada-uno",
"clean_url": "dailyhive.com",
"excerpt": "Pizza and game nights are a match made in heaven. Pizza Pizza has partnered with Mattel Canada for the ultimate package deal.",
"summary": "Pizza and game nights are a match made in heaven â even Pizza Pizza knows that. The Canadian chain has partnered with Mattel Canada for the ultimate package deal.\nReturning for another year is the pizza chain's UNO collab but this time it features a new limited-edition Pizza Pizza or Pizza 73 branded UNO deck with every featured UNO combo purchase.\nThe decks feature pizza art and a surprise bonus offer too.\n\n \nView this post on Instagram\n A post shared by Pizza Pizza (@pizzapizzaltd)\n\n 'For over 50 years, UNO has become a staple at game nights across the country, bringing families and friends together through gameplay,' said Jennifer Gileno, Head of Licensing and Retail Development for Mattel Canada.",
"rights": null,
"rank": 9543,
"topic": "news",
"country": "CA",
"language": "en",
"authors": [],
"media": "https://images.dailyhive.com/20220318132250/pizza-pizza-uno-500x256.jpg",
"is_opinion": false,
"twitter_account": "https://dailyhive.com/vancouver/pizza-pizza-mattel-canada-uno",
"_score": 14.017945,
"_id": "feca5f5fe473e561bf0b8c11b01b87bf"
}
],
"user_input": {
"q": "pizza",
"search_in": [
"title_summary"
],
"lang": null,
"not_lang": null,
"countries": null,
"not_countries": null,
"from": "2022-03-15 00:00:00",
"to": null,
"ranked_only": "True",
"from_rank": null,
"to_rank": null,
"sort_by": "relevancy",
"page": 1,
"size": 1,
"sources": null,
"not_sources": null,
"topic": null,
"published_date_precision": null
}
}
为了解码数据,我创建了以下结构:
struct ArticleModel: Codable {
let totalPages: Int
let articles: [Articles]
let numOfResults: Int
enum CodingKeys: String, CodingKey {
case totalPages = "total_pages"
case articles = "articles"
case numOfResults = "total_hits"
}
}
struct Articles: Codable {
let id: String
let articleTitle: String
let date: String
let url: String
let content: String
let author: String?
let topic: String
let imageUrl: String?
enum CodingKeys: String, CodingKey {
case id = "_id"
case articleTitle = "title"
case content = "summary"
case author = "author"
case url = "link"
case date = "published_date"
case topic = "topic"
case imageUrl = "media"
}
}
我在我的应用程序中使用分页,我的初始抓取工作正常,没有问题。然而,当向下滚动到UITableView的底部时,我触发了另一个获取请求(对于下一批数据,即第2页的数据),我在控制台中收到以下错误:
keyNotFound(编码键(stringValue:“总页数”,intValue:无),Swift。解码错误。Context(codingPath:[],debugDescription:“没有与键CodingKeys关联的值(stringValue:“总计页面”,intValue:nil)(“总计页面”)”,参考误差:零)
分页工作正常,数据批按原样检索。。但我不明白为什么这个错误会不断出现,为什么只有从第二次开始抓取时才会发生。
编辑#1
:无论我取哪个查询或页面-
total_pages
总是在结果中返回,并且总是有一个值。
编辑#2
:我试着做了
总页数
可选,但控制台中的错误将更改为:
keyNotFound(CodingKeys(stringValue:“articles”,intValue:nil),Swift。解码错误。Context(codingPath:[],debugDescription:“没有与键codingkey(stringValue:“articles”,intValue:nil)关联的值”(“articles”)”,参考误差:零)
这也没有任何意义,因为我在屏幕上看到了新的结果。。
编辑#3
:这是我在第二页得到的回复-
来自邮递员:
{
"status": "ok",
"total_hits": 10000,
"page": 2,
"total_pages": 10000,
"page_size": 1,
"articles": [
{
"title": "Broadway & Beyond Hosts Webinar on Anti-Racist Stage Management Practices",
"author": "Raven Brunner",
"published_date": "2022-03-21 17:17:43",
"published_date_precision": "full",
"link": "https://playbill.com/article/broadway-beyond-hosts-webinar-on-anti-racist-stage-management-practices",
"clean_url": "playbill.com",
"excerpt": "The webinar will be led by veteran stage managers Narda E. Alcorn and Lisa Porter.",
"summary": "Education News Education News Education News Education News Theatre Alternatives Industry News Industry News Industry News Education News Education News Education News Education News Education News Education News Industry News Industry News Industry News Education News Education News Industry News Industry News Education News Education News Industry News Education News Industry News Education News Industry News Industry News Education News Education News Industry News Education News Industry New",
"rights": "playbill.com",
"rank": 5215,
"topic": "entertainment",
"country": "US",
"language": "en",
"authors": [
"Raven Brunner"
],
"media": "https://assets.playbill.com/editorial/_1200x630_crop_center-center_82_none/Narda-E.-Alcorn-and-Lisa-Porter_HR.jpg?mtime=1647876883",
"is_opinion": false,
"twitter_account": "@playbill",
"_score": 5.5872316,
"_id": "7e297f463684c344e3bb9b70d6229fbf"
}
],
"user_input": {
"q": "news",
"search_in": [
"title_summary"
],
"lang": null,
"not_lang": null,
"countries": null,
"not_countries": null,
"from": "2022-03-15 00:00:00",
"to": null,
"ranked_only": "True",
"from_rank": null,
"to_rank": null,
"sort_by": "relevancy",
"page": 2,
"size": 1,
"sources": null,
"not_sources": null,
"topic": null,
"published_date_precision": null
}
}
从控制台:
ArticleModel(totalPages: 10000, articles: [Dispatcher_Development.Articles(id: "7e297f463684c344e3bb9b70d6229fbf", articleTitle: "Broadway & Beyond Hosts Webinar on Anti-Racist Stage Management Practices", date: "2022-03-21 17:17:43", url: "https://playbill.com/article/broadway-beyond-hosts-webinar-on-anti-racist-stage-management-practices", content: "Education News Education News Education News Education News Theatre Alternatives Industry News Industry News Industry News Education News Education News Education News Education News Education News Education News Industry News Industry News Industry News Education News Education News Industry News Industry News Education News Education News Industry News Education News Industry News Education News Industry News Industry News Education News Education News Industry News Education News Industry New", author: Optional("Raven Brunner"), topic: "entertainment", imageUrl: Optional("https://assets.playbill.com/editorial/_1200x630_crop_center-center_82_none/Narda-E.-Alcorn-and-Lisa-Porter_HR.jpg?mtime=1647876883"))], numOfResults: 10000)
以防万一——以下是我如何检测到用户一直向下滚动:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let position = scrollView.contentOffset.y
if position > (tableView.contentSize.height - 100 - scrollView.frame.size.height) {
fetchNewsFromAPI() {
DispatchQueue.main.async {
self.tableView.tableFooterView = nil
}
}
}
}
这是负责获取数据的函数:
func fetchNewsFromAPI(completionHandler: @escaping () -> ()) {
let alamofireQuery = AlamofireManager(from: "\(Constants.apiCalls.newsUrl)?q=news&page_size=\(amountToFetch)&page=\(currentPaginationPage)")
if !alamofireQuery.isPaginating && currentPaginationPage <= totalPaginationPages {
alamofireQuery.executeGetQuery(){
(result: Result<ArticleModel,Error>) in
switch result {
case .success(let response):
self.currentPaginationPage += 1
self.totalPaginationPages = response.totalPages
self.newsArray.append(contentsOf: response.articles)
DispatchQueue.main.async {
self.dataSource.models = self.newsArray
self.tableView.reloadData()
}
case .failure(let error):
print(error)
}
completionHandler()
}
}
}
这是我的Alamofire文件中的executeQuery函数:
func executeGetQuery<T>(completion: @escaping (Result<T, Error>) -> Void) where T: Codable {
isPaginating = true
AF.request(url, method: .get, headers: headers).responseData(completionHandler: { response in
do {
switch response.result {
case .success:
completion(.success(try JSONDecoder().decode(T.self, from: response.data ?? Data())))
self.isPaginating = false
case .failure(let error):
completion(.failure(error))
}
} catch let error {
completion(.failure(error))
self.isPaginating = false
}
})
}