Не удается отобразить полученные данные API в табличном представлении в Swift - PullRequest
0 голосов
/ 28 января 2020

Цель

  • Моя цель - отобразить ближайшие рестораны в моем районе с помощью API Zomato и быстро

Ошибка

  • Когда Я пытаюсь заполнить массив для отображения ближайших ресторанов в моем районе, код не вводится для l oop внутри viewDidLoad () для заполнения массива.

Код

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

Результат

  • Я хочу, чтобы ближайшие рестораны в моем районе отображались в виде таблицы

Любая помощь ценится

Ответы [ 2 ]

1 голос
/ 28 января 2020

Этот код вообще не имеет смысла

 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 пуст, поэтому l oop никогда не будет выполнен. Во-вторых, вы создаете новый экземпляр Welcome вне l oop, поэтому всегда будет использоваться один и тот же экземпляр.

Короче говоря, весь l oop не имеет смысла, просто присвойте значение 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()
 }
1 голос
/ 28 января 2020

Прежде всего, ваш self.nearby_restaurant считается в 0, поэтому для l oop никогда не будет выполнено. Кроме того, вам нужно перезагрузить табличное представление после получения данных.

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()
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...