Display The Users Reviews In A TableView
I'm trying to adding in a tableView the users reviews taken from google places API
"reviews" : [
{
"author_name" : "Robert Ardill",
"author_url" : "https://www.google.com/maps/contrib/106422854611155436041/reviews",
"language" : "en",
"profile_photo_url" : "https://lh3.googleusercontent.com/-T47KxWuAoJU/AAAAAAAAAAI/AAAAAAAAAZo/BDmyI12BZAs/s128-c0x00000000-cc-rp-mo-ba1/photo.jpg",
"rating" : 5,
"relative_time_description" : "a month ago",
"text" : "Awesome offices. Great facilities, location and views. Staff are great hosts",
"time" : 1491144016
}
],
https://developers.google.com/places/web-service/details, for now i'm trying to add only the rating, author_name and text, this is my custom tableViewCell
import UIKit
class myReviewTableCell: UITableViewCell {
@IBOutlet weak var revText: UITextView!
@IBOutlet weak var revRating: UIImageView!
@IBOutlet weak var revAuthor: UILabel!
var place: EClass?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func revSelect(place:Eclass) {
NearbyPlaces.getPlaceDetails(place: place) { (place) in
DispatchQueue.main.async {
if let rev = place.details?["reviews"] as? [String:Any] {
}
}
}
}
}
where i need to build properly the func revSelect(place:Eclass)
and after call it in my cellForRowAt. I already tried to add other parameters like
if (place.details?["website"] as? String) != nil {
self.webButton.isHidden = false
}
else {
self.webButton.isHidden = true
}
if let phoneNumber = place.details?["international_phone_number"] as? String {
self.myLabel4.text = "\(phoneNumber)"
}
else {
self.myLabel4.isHidden = true
}
}
}
and they work well, but reviews is an array so is different, i also tried to follow the logic of the parameters "geometry"
if let g = placeInfo["geometry"] as? [String:Any] {
if let l = g["location"] as? [String:Double] {
if let lat = l["lat"], let lng = l["lng"] {
location = CLLocationCoordinate2D.init(latitude: lat, longitude: lng)
}
}
}
that i added in another class, but it did not work. So what i have to do in my func revSelect to make rev.Author.text = "author_name" , revText = "text" etc. ?? (I already asked before about this but i could not solve the problem)
//UPDATE
this is the func that i use to get place details
static func getPlaceDetails(place:EClass, completion: @escaping (EClass) -> Void) {
guard place.details == nil else {
completion(place)
return
}
var params : [String : Any]
params = [
"key" : AppDelegate.googlePlacesAPIKey,
"placeid" : place.placeId,
]
Alamofire.request(googlePlaceDetailsHost, parameters: params, encoding: URLEncoding(destination: .queryString)).responseJSON { response in
let value = response.result.value as? [String : Any]
place.details = (value)?["result"] as? [String : Any]
/* print(((value)?["result"] as? [String : Any] ?? [String : Any]()).debugDescription) */
completion(place)
}
}
Answer
You just need to research JSON parsing in Swift. This article would be a good read.
JSON is quite easy to read once you understand how it is structured. You just need to map each type properly. Swift 4 Introduced the Codable protocol which when combined with JSONDecoder give you a much better way of parsing and using this data.
struct Response: Codable {
var reviews: [Review]
}
struct Review: Codable {
var authorName: String
var authorUrl: String
var rating: Int
var text: String
enum CodingKeys: String, CodingKey {
case authorName = "author_name"
case authorUrl = "author_url"
case rating
case text
}
}
let data = """
{
"reviews" : [{
"author_name" : "Robert Ardill",
"author_url" : "https://www.google.com/maps/contrib/106422854611155436041/reviews",
"language" : "en",
"profile_photo_url" : "https://lh3.googleusercontent.com/-T47KxWuAoJU/AAAAAAAAAAI/AAAAAAAAAZo/BDmyI12BZAs/s128-c0x00000000-cc-rp-mo-ba1/photo.jpg",
"rating" : 5,
"relative_time_description" : "a month ago",
"text" : "Awesome offices. Great facilities, location and views. Staff are great hosts",
"time" : 1491144016
}]
}
""".data(using: .utf8)
guard let data = data else { throw NSError() }
let response = try? JSONDecoder().decode(Response.self, from: data)
let reviews = response?.reviews // array of reviews
let review = reviews?.first // first one from the list (if any)
print(review?.authorName)
print(review?.rating)
So using the example above, I have created a Review type and mapped the properties of this type to the types in the JSON response. Then we can use JSONDecoder to do the rest of the work for us.
OUTPUT:
Optional("Robert Ardill")
Optional(5)
UPDATE:
You need to do something like this, but you may need to change the structs structure based on the response values.
Alamofire.request(googlePlaceDetailsHost, parameters: params, encoding: URLEncoding(destination: .queryString)).responseJSON { response in
guard let data = response.data else { throw NSError() }
let response = try? JSONDecoder().decode(Response.self, from: data)
let reviews = response?.reviews // array of reviews
completion(reviews?.first)
}
Related Questions
- → Function Undefined in Axios promise
- → What are the pluses/minuses of different ways to configure GPIOs on the Beaglebone Black?
- → Click to navigate on mobile devices
- → Playing Video - Server is not correctly configured - 12939
- → How to allow api access to android or ios app only(laravel)?
- → Axios array map callback
- → Access the Camera and CameraRoll on Android using React Native?
- → Update React [Native] View on Day Change
- → Shopify iOS SDK - issue converting BuyProductVariant to BuyProduct
- → BigCommerce and shopify API
- → Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `ListView`
- → React Native - Differences between Android and IOS
- → What is the difference between React Native and React?