无法在 swift 的表视图中显示检索到的 API 数据



目标

  • 我的目标是通过使用Zomato API和swift显示我所在地区最近的餐厅

错误

  • 当我尝试填充数组以显示我所在地区最近的餐馆时,代码不会在 viewDidLoad(( 中输入 for 循环来填充数组。

法典

餐厅表视图控制器.swift

import UIKit
import Foundation
import CoreLocation
class RestaurantTableViewController: UITableViewController, CLLocationManagerDelegate {
let apiKey: String = "e06745d59aa6170842e9760500129d63"
let cellIdentifier: String = "restaurantCell"
var restaurantImages: [URL] = []
var locationManager = CLLocationManager()
var restInfoVC = RestaurantInfoViewController()
var nearby_restaurants = [Welcome]()
// MARK: Lifecycle methods
override func viewDidLoad() {
super.viewDidLoad()
let urlString = """
https://developers.zomato.com/api/v2.1/geocode?lat=(38.390625)&lon=(27.02147911555935)
"""
let url = URL(string: urlString)

if url != nil {
var request = URLRequest(url: url!)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue(apiKey, forHTTPHeaderField: "user-key")
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil else { return }
let httpResponse = response as! HTTPURLResponse
if httpResponse.statusCode == 200 {
do {
/*
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String:Any]
guard let array = json!["nearby_restaurants"] else { return }
print(array)
*/
let decoder = JSONDecoder()
let list = try decoder.decode(Welcome.self, from: data)
var welcome = Welcome()
// print(list.nearbyRestaurants[1].restaurant.menuURL)
for index in 0..<self.nearby_restaurants.count {
welcome.nearbyRestaurants[index].restaurant.name = list.nearbyRestaurants[index].restaurant.name
welcome.nearbyRestaurants[index].restaurant.url = list.nearbyRestaurants[index].restaurant.url
welcome.nearbyRestaurants[index].restaurant.thumb = list.nearbyRestaurants[index].restaurant.thumb
welcome.nearbyRestaurants[index].restaurant.userRating.ratingText = list.nearbyRestaurants[index].restaurant.userRating.ratingText
self.nearby_restaurants.append(welcome)
}
} catch {
print("Error is: (error)")
}
}
}.resume()
}
}
}
extension RestaurantTableViewController {
// MARK: Tableview delegate methods
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return nearby_restaurants.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! RestaurantTableViewCell
cell.restaurantName.text = nearby_restaurants[indexPath.row].nearbyRestaurants[indexPath.row].restaurant.name
cell.restaurantRating.text = nearby_restaurants[indexPath.row].nearbyRestaurants[indexPath.row].restaurant.userRating.ratingText
do {
//let data = try Data(contentsOf: URL(string: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSk90on-LRDhhFc7FRyRjR_yuv1OBKXHcJclO07h5zpZOrs-QJH&s")!),
let data = try Data(contentsOf: URL(string: nearby_restaurants[indexPath.row].nearbyRestaurants[indexPath.row].restaurant.photosURL)!)
let imageView = UIImageView(image: UIImage(data: data))
imageView.contentMode = UIView.ContentMode.scaleAspectFit
DispatchQueue.main.async {
cell.restaurantImage.image = imageView.image
}
} catch _ {
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let url = URL(string: nearby_restaurants[indexPath.row].nearbyRestaurants[indexPath.row].restaurant.url)!
restInfoVC.restaurantWebView.load(URLRequest(url: url))
/*
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let destination = storyboard.instantiateViewController(withIdentifier: "RestaurantInfoViewController") as! RestaurantInfoViewController
navigationController?.pushViewController(destination, animated: true)
*/
}
}
import Foundation
// MARK: - Welcome
struct Welcome: Decodable {
var location: WelcomeLocation
var popularity: Popularity
var link: String
var nearbyRestaurants: [NearbyRestaurant]
enum CodingKeys: String, CodingKey {
case location, popularity, link
case nearbyRestaurants = "nearby_restaurants"
}
init() {
location = WelcomeLocation()
popularity = Popularity()
link = ""
nearbyRestaurants = []
}
}
// MARK: - WelcomeLocation
struct WelcomeLocation: Decodable {
var entityType: String
var entityID: Int
var title, latitude, longitude: String
var cityID: Int
var cityName: String
var countryID: Int
var countryName: String
enum CodingKeys: String, CodingKey {
case entityType = "entity_type"
case entityID = "entity_id"
case title, latitude, longitude
case cityID = "city_id"
case cityName = "city_name"
case countryID = "country_id"
case countryName = "country_name"
}
init() {
entityID = 0
entityType = ""
title = ""
latitude = ""
longitude = ""
cityID = 0
cityName = ""
countryID = 0
countryName = ""
}
}
// MARK: - NearbyRestaurant
struct NearbyRestaurant: Decodable {
var restaurant: Restaurant
}
// MARK: - Restaurant
struct Restaurant: Decodable {
var r: R
var apikey, id, name: String
var url: String
var location: RestaurantLocation
var switchToOrderMenu: Int
var cuisines: String
var averageCostForTwo, priceRange: Int
var currency: String
var offers: [JSONAny]
var opentableSupport, isZomatoBookRes: Int
var mezzoProvider: String
var isBookFormWebView: Int
var bookFormWebViewURL, bookAgainURL, thumb: String
var userRating: UserRating
var photosURL, menuURL: String
var featuredImage: String
var hasOnlineDelivery, isDeliveringNow: Int
var includeBogoOffers: Bool
var deeplink: String
var isTableReservationSupported, hasTableBooking: Int
var eventsURL: String
enum CodingKeys: String, CodingKey {
case r = "R"
case apikey, id, name, url, location
case switchToOrderMenu = "switch_to_order_menu"
case cuisines
case averageCostForTwo = "average_cost_for_two"
case priceRange = "price_range"
case currency, offers
case opentableSupport = "opentable_support"
case isZomatoBookRes = "is_zomato_book_res"
case mezzoProvider = "mezzo_provider"
case isBookFormWebView = "is_book_form_web_view"
case bookFormWebViewURL = "book_form_web_view_url"
case bookAgainURL = "book_again_url"
case thumb
case userRating = "user_rating"
case photosURL = "photos_url"
case menuURL = "menu_url"
case featuredImage = "featured_image"
case hasOnlineDelivery = "has_online_delivery"
case isDeliveringNow = "is_delivering_now"
case includeBogoOffers = "include_bogo_offers"
case deeplink
case isTableReservationSupported = "is_table_reservation_supported"
case hasTableBooking = "has_table_booking"
case eventsURL = "events_url"
}
}
// MARK: - UserRating
struct UserRating: Decodable {
var aggregateRating: AggregateRating
var ratingText, ratingColor: String
var ratingObj: RatingObj
var votes: AggregateRating
enum CodingKeys: String, CodingKey {
case aggregateRating = "aggregate_rating"
case ratingText = "rating_text"
case ratingColor = "rating_color"
case ratingObj = "rating_obj"
case votes
}
}
enum AggregateRating: Decodable {
case integer(Int)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Int.self) {
self = .integer(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(AggregateRating.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for AggregateRating"))
}
}

结果

  • 我希望在表格视图中显示我所在地区最近的餐馆

任何帮助不胜感激

这段代码根本没有意义

let decoder = JSONDecoder()
let list = try decoder.decode(Welcome.self, from: data)
var welcome = Welcome()
// print(list.nearbyRestaurants[1].restaurant.menuURL)
for index in 0..<self.nearby_restaurants.count {
welcome.nearbyRestaurants[index].restaurant.name = list.nearbyRestaurants[index].restaurant.name
welcome.nearbyRestaurants[index].restaurant.url = list.nearbyRestaurants[index].restaurant.url
welcome.nearbyRestaurants[index].restaurant.thumb = list.nearbyRestaurants[index].restaurant.thumb
welcome.nearbyRestaurants[index].restaurant.userRating.ratingText = list.nearbyRestaurants[index].restaurant.userRating.ratingText
self.nearby_restaurants.append(welcome)
}

首先,数组nearbyRestaurants是空的,因此循环永远不会被执行。其次,您将在循环之外创建新的Welcome实例,因此始终使用相同的实例。

长话短说,整个循环毫无意义,只需将welcome.nearbyRestaurants的值分配给nearby_restaurants(变量名称list具有误导性(,您必须在主线程上重新加载表视图

let decoder = JSONDecoder()
let welcome = try decoder.decode(Welcome.self, from: data)
self.nearby_restaurants = welcome.nearbyRestaurants
DispatchQueue.main.async {
self.tableView.reloadData()
}

首先,你的self.nearby_restaurant计数在 0 中,所以 for 循环永远不会被执行。此外,您需要在获取数据后重新加载表视图。

self.tableView.reloadData()

所以这是你的viewDidLoad()应该是什么样子

var nearby_restaurants : Welcome!
override func viewDidLoad() {
super.viewDidLoad()
let urlString = """
https://developers.zomato.com/api/v2.1/geocode?lat=(38.390625)&lon=(27.02147911555935)
"""
let url = URL(string: urlString)

if url != nil {
var request = URLRequest(url: url!)
request.httpMethod = "GET"
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue(apiKey, forHTTPHeaderField: "user-key")
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil else { return }
let httpResponse = response as! HTTPURLResponse
if httpResponse.statusCode == 200 {
do {
let decoder = JSONDecoder()
let welcomeData = try decoder.decode(Welcome.self, from: data)
self.nearby_restaurants = welcomeData.nearbyRestaurants
} catch {
print("Error is: (error)")
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}.resume()
}
}

最新更新