So I'm creating an app that uses the Google Places API to gather a list of restaurants. Using the API provides me with a JSON file full of details about each location like lat, long, rating, priceLevel, openNow, photos, etc. Below is the code used to gather said JSON from my given parameters:
func performGoogleSearch(radius: Double, type: String, price: Int ) {
let location = locationManager.location?.coordinate
let url: URL = URL(string: "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=\(location?.latitude ?? 0),\(location?.longitude ?? 0)&radius=\(radius * 1609.34)&type=restaurant&maxprice=\(price)&key=AIzaSyBF0uwjr6BZc-Y-0kPsMBq2zNkl5EArioQ")!
let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
print(NSString(data: data!, encoding: String.Encoding.utf8.rawValue))
}
task.resume()
}
The data returned is a JSON like the following:
{
"html_attributions" : [],
"results" : [
{
"geometry" : {
"location" : {
"lat" : 37.7867167,
"lng" : -122.4111737
},
"viewport" : {
"northeast" : {
"lat" : 37.7881962302915,
"lng" : -122.4098846697085
},
"southwest" : {
"lat" : 37.7854982697085,
"lng" : -122.4125826302915
}
}
},
"icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/lodging-71.png",
"id" : "3344890deedcb97b1c2d64814f92a02510ba39c8",
"name" : "Clift San Francisco",
"opening_hours" : {
"open_now" : false,
"weekday_text" : []
},
"photos" : [
{
"height" : 900,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/114937580614387417622/photos\"\u003eClift San Francisco\u003c/a\u003e"
],
"photo_reference" : "CmRaAAAAwpWxfFJMJnK8G-LWJehCyUH5PFtepMF26XkZnXDRDo0wJMe-dAXLZ0zXGDmoEMi9n8YF5rYhgnr-EoDZFUawtiITYYocTJDAAjo1hw0sos4wVpfnx186o6pPgQWEv1f0EhDrydRti0bHEkhY4FNANV_KGhRmH8m7e6mO1sR2FlFxFuo5oSl00g",
"width" : 1155
}
],
"place_id" : "ChIJFUBxSY6AhYARwOaLV7TsLjw",
"price_level" : 4,
"rating" : 4.1,
"reference" : "CmRRAAAAA4IUvt3mHf2_QejiFA1acdgH2pg5h1_6GYDuVt-bzSwHqieSXmCAye5FRGJ0EjIM03WICU82MuKOiHor65j-e8rCDNEkltQnpoUX4AbCfRdybuqIPS5FxNsV_905or7BEhDNu3bKvzktrh2USu0zSNtoGhSkqf9WV1snRVufZ11kN6YgF961YQ",
"scope" : "GOOGLE",
"types" : [
"night_club",
"bar",
"lodging",
"restaurant",
"food",
"point_of_interest",
"establishment"
],
"vicinity" : "495 Geary Street, San Francisco"
},
{
"geometry" : {
"location" : {
"lat" : 37.78988329999999,
"lng" : -122.4091511
},
"viewport" : {
"northeast" : {
"lat" : 37.79135163029149,
"lng" : -122.4078268197085
},
"southwest" : {
"lat" : 37.78865366970849,
"lng" : -122.4105247802915
}
}
},
"icon" : "https://maps.gstatic.com/mapfiles/place_api/icons/lodging-71.png",
"id" : "547ceb15210b70b8734500183410bb10c644c395",
"name" : "Cornell Hotel De France",
"opening_hours" : {
"open_now" : true,
"weekday_text" : []
},
"photos" : [
{
"height" : 315,
"html_attributions" : [
"\u003ca href=\"https://maps.google.com/maps/contrib/114711934191765864568/photos\"\u003eCornell Hotel De France\u003c/a\u003e"
],
"photo_reference" : "CmRaAAAAJ3kTtFbeGT-8NWKbf9TPlN6gL6daO5zKq9DNZnzShZ-CcPUJnxMaVZybHZ0sGefM72WV01VcXr1AJWNKOSifZ63DIxxutKJ0ecqPUkM73LZLM-LO_eqsaWBRH8QN6PLYEhDykcPC3JAyDEDWpdiu3FP8GhRiJrTRNpnYQi1DDztzCRVKAM4N_A",
"width" : 851
}
],
"place_id" : "ChIJs6F3JYyAhYARDiVdBrmivCs",
"price_level" : 4,
"rating" : 4.2,
"reference" : "CmRRAAAAK05VMbTrE3cDxZreuM-Z0rbXcfdT4nflU0D17oCIwaF2RVbF85ch-1qKfRAGtMPxuuBvzw9sO-Y1rwRin-fEmzvgtiPsy8X_R2kfzh7rHX8iS8gJKc1QyTk2H4XU2O4hEhDMcIcjK5fWFvnGrJWxHgC6GhQAOkKXMCm7IjhOeOD__ZqzFlosmg",
"scope" : "GOOGLE",
"types" : [
"clothing_store",
"store",
"lodging",
"restaurant",
"food",
"point_of_interest",
"establishment"
],
"vicinity" : "715 Bush Street, San Francisco"
}
],
"status" : "OK"
}
I have an object called "Location" that hopes to take the JSON as a parameter to fill in its respective values. I would like to get to the point where I can take this JSON and turn it into an array of my "Location" struct populated with one "Location" for each restaurant returned in the Google Places API JSON.
Here is the "Location" struct:
import Foundation
struct Location: Codable {
var lat: Double
var long: Double
var icon: String?
var id: String?
var name: String
var openNow: Bool?
var photos: [String : Any]?
var placeID: String?
var priceLevel: Int?
var rating: Double?
var types: [String]?
init?(json: [String: Any]) {
guard let lat = json["lat"] as? Double,
let long = json["lng"] as? Double,
let icon = json["icon"] as? String,
let id = json["id"] as? String,
let name = json["name"] as? String,
let openNow = json["open_now"] as? Bool,
let photos = json["photos"] as? [String : Any],
let placeID = json ["place_id"] as? String,
let priceLevel = json["price_level"] as? Int,
let rating = json["rating"] as? Double,
let types = json["types"] as? [String]? else {
return nil
}
self.lat = lat
self.long = long
self.icon = icon
self.id = id
self.name = name
self.openNow = openNow
self.photos = photos
self.placeID = placeID
self.priceLevel = priceLevel
self.rating = rating
self.types = types
}
}
This struct is a start but is clearly lacking as I do not know how to go about taking the data from the JSON to make an array of this "Location" struct. Any guidance would be appreciated.
You can use JSONDecoder
let decoder = JSONDecoder()
do {
let locations = try decoder.decode([Location].self, from: yourJson)
print(locations)
} catch {
print(error.localizedDescription)
}
Also you can nest structs to represent your data which you're probably going to have to do. Have a look at "More Complex Nested Response" on this guide to JSON parsing
I eventually changed my "Location" struct to
Not be codable
Take each property as a parameter as opposed to taking the whole JSON dictionary as the parameter
In the "performGoogleSearch()" function, I essentially had to keep converting values of the dictionary into dictionaries themselves in order to reach deeper into the file. I then used each value I could get out of the JSON file and used them to create an object of my class. I then appended each object to my array of results.
func performGoogleSearch(radius: Double, type: String, price: Int ) {
let location = locationManager.location?.coordinate
let url: URL = URL(string: "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=\(location?.latitude ?? 0),\(location?.longitude ?? 0)&radius=\(radius * 1609.34)&type=restaurant&maxprice=\(price)&key=AIzaSyBF0uwjr6BZc-Y-0kPsMBq2zNkl5EArioQ")!
let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
let jsonObject = try? JSONSerialization.jsonObject(with: data! as Data, options: [])
if let jsonArray = jsonObject as? [String: Any] {
if let results = jsonArray["results"] as! [Any]?{
for result in results {
if let locationDictionary = result as? [String : Any] {
let geometry = locationDictionary["geometry"]! as! [String : Any]
let location = geometry["location"]! as! [String : Any]
let lat = location["lat"]
let long = location["lng"]
let openingHours = locationDictionary["opening_hours"] as? [String : Any]
let openNow = openingHours?["open_now"]
let photos = locationDictionary["photos"] as? [[String : Any]]
let newLocation = Location(lat: lat as! Double, long: long as! Double, id: locationDictionary["id"] as? String, name: locationDictionary["name"] as! String, openNow: openNow as? Int, photos: photos, placeID: locationDictionary["place_id"] as? String, priceLevel: locationDictionary["price_level"] as? Int, rating: locationDictionary["rating"] as? Double, types: locationDictionary["types"] as? [String])
googleResults.append(newLocation!)
}
}
print("Results: \(googleResults.count)")
let randomInt = Int(arc4random_uniform(UInt32(googleResults.count)))
print("RandomInt: \(randomInt)")
if googleResults.count != 0 {
self.googleResult = googleResults[randomInt]
self.annotation = MapBoxAnnotation(coordinate: CLLocationCoordinate2D(latitude: (self.self.googleResult?.lat)!, longitude: (self.self.googleResult?.long)!), title: self.googleResult?.name, subtitle: nil)
}
}
}
DispatchQueue.main.async {
self.animateResultView()
}
}
task.resume()
Location struct:
struct Location {
var lat: Double
var long: Double
var id: String?
var name: String
var openNow: Int?
var photos: [[String : Any]]?
var placeID: String?
var priceLevel: Int?
var rating: Double?
var types: [String]?
init?(lat: Double, long: Double, id: String?, name: String, openNow: Int?, photos: [[String : Any]]?, placeID: String?, priceLevel: Int?, rating: Double?, types: [String]?) {
self.lat = lat
self.long = long
self.id = id
self.name = name
self.openNow = openNow
self.photos = photos
self.placeID = placeID
self.priceLevel = priceLevel
self.rating = rating
self.types = types
}
}
Related
I need to parse out "choices" and save 123347 and save "option" to a string from the following String:
{
"type" : "radiobuttons",
"patient" : false,
"text" : "How are you today",
"id" : 63339,
"position" : 2,
"options" : "123344:ok today;123345:see you tomorrow;123346:call friend;123347:call lisa;",
"required" : true,
"choices" : {
"123347" : {
"value" : 3,
"option" : "iOS"
},
"123345" : {
"option" : "Android",
"value" : 1
},
"123346" : {
"option" : "Windows",
"value" : 2
},
"123344" : {
"option" : "MAC",
"value" : 0
}
}
}
let json = try? JSONSerialization.jsonObject(with: str, options: [])
Swift 5
Try to serialize and decode it
let jsonResponse = try JSONSerialization.data(withJSONObject: responseObject as Any, options: JSONSerialization.WritingOptions.sortedKeys)
let customObject = try JSONDecoder().decode(CustomObject.self, from: jsonResponse)
guard let requiredChoice = customObject.choices["123347"] else{
return
}
let option = requiredChoice.option
print(option)
CustomObject for your json:
struct CustomObject: Codable {
let type: String
let patient: Bool
let text: String
let id, position: Int
let options: String
let customObjectRequired: Bool
let choices: [String: Choice]
enum CodingKeys: String, CodingKey {
case type, patient, text, id, position, options
case customObjectRequired = "required"
case choices
}
}
struct Choice: Codable {
let option: String
let value: Int
}
There are many tools available to easily create struct/class for your json:
E.g: https://app.quicktype.io
im trying to dispaly array object come from api response as [[String: Any]] at table view
and thats my struct
class CategoriesDep: NSObject {
var depName: String
var depImage: String
var subName = [subData]()
init?(dict: [String: JSON]) {
guard let image = dict["main_department_image"]?.imagePath, !image.isEmpty else { return nil }
self.depImage = image
self.depName = (dict["main_department_name"]?.string)!
}
struct subData {
var dep: String
init(dic: [String: Any]) {
self.dep = dic["sub_department_name"] as! String
}
}
}
Please check below code to parse your json
class CategoriesDep: NSObject {
var depName: String
var depImage: String
var subName = [subData]()
init?(dict: [String: Any]) {
guard let image = dict["main_department_image"] as? String, !image.isEmpty else { return nil }
self.depImage = image
self.depName = (dict["main_department_name"] as? String)!
subName = []
for subDict in (dict["sub_depart"] as? [[String:Any]] ?? []){
subName.append(subData(dic: subDict))
}
}
}
struct subData {
var dep: String
var image :String
var id : String
init(dic: [String: Any]) {
self.dep = dic["sub_department_name"] as! String
self.image = dic["sub_department_image"] as! String
self.id = dic["sub_department_id"] as! String
}
}
and if you want to access subdata struct out side of CategoriesDep class then declare structure outside CategoriesDep class
Parse your given json Respoise like
let json = [
[ "sub_depart" : [
[ "sub_department_name" : "hos", "sub_department_id" : "6", "sub_department_image" : "23.jpg"
]
],
"main_department_id" : "2",
"main_department_name" : "main ",
"main_department_image" : "14.jpg"
],
]
var catDepart : [CategoriesDep] = []
for dict in json {
catDepart.append(CategoriesDep(dict: dict)!)
}
print(catDepart[0].subName[0].dep)
You could use Codabel protocol to be more swifty ;) and cleaning up the code.
let jsonString = "[{\"sub_depart\" : [ {\"sub_department_name\" : \"hos\", \"sub_department_id\" : \"6\", \"sub_department_image\" : \"23.jpg\" } ], \"main_department_id\" : \"2\", \"main_department_name\" : \"main \", \"main_department_image\" : \"14.jpg\"}]"
struct CategoriesDep: Codable {
let mainDepartmentName: String
let mainDepartmentImage: String
let mainDepartmentId: String
var subDepart: [SubData] = []
}
struct SubData: Codable {
let subDepartmentName: String
let subDepartmentImage: String
let subDepartmentId: String
}
if let jsonData = jsonString.data(using: .utf8) {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
var departments: [CategoriesDep]? = try? decoder.decode([CategoriesDep].self, from: jsonData)
...
}
Note the decoder.keyDecodingStrategy = .convertFromSnakeCase here which is mapping the underscore (snake_case) API property names to your camelCase ones.
If you need different property names you have to implement CodingKeys enum to map them.
For more detailed information check this link.
let APIUrl = NSURL(string:"https://api.openweathermap.org/data/2.5/weather?lat=(currentLocation.coordinate.latitude)&lon=(currentLocation.coordinate.longitude)&appid=e7b2054dc37b1f464d912c00dd309595&units=Metric%22")
let request = URLRequest(url:APIUrl! as URL)
let dataTask = URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
print(error ?? "Error is empty.")
} else {
let httpResponse = response as? HTTPURLResponse
print(httpResponse ?? "HTTP response is empty.")
}
guard let responseData = data else {
print("Error: did not receive data")
return
}
do {
let weatherData = try JSONDecoder().decode(MyWeather.self, from: responseData)
let ggtemp = weatherData.main?.temp
print(ggtemp!, "THIS IS THE TEMP")
DispatchQueue.main.async {
self.tempDisplay.text = String(format: "%.1f", ggtemp!)
}
} catch {
print("error parsing response from POST on /todos")
return
}
})
dataTask.resume()
}
I want to get the temperature of my current Location.
Here is what I get when app runs:
<NSHTTPURLResponse: 0x28322fbe0> { URL: https://api.openweathermap.org/data/2.5/weather?lat=(currentLocation.coordinate.latitude)&lon=(currentLocation.coordinate.longitude)&appid=e7b2054dc37b1f464d912c00dd309595&units=Metric%22 } { Status Code: 400, Headers {
"Access-Control-Allow-Credentials" = (
true
);
"Access-Control-Allow-Methods" = (
"GET, POST"
);
"Access-Control-Allow-Origin" = (
"*"
);
Connection = (
"keep-alive"
);
"Content-Length" = (
78
);
"Content-Type" = (
"application/json; charset=utf-8"
);
Date = (
"Sun, 21 Oct 2018 09:57:38 GMT"
);
Server = (
openresty
);
"X-Cache-Key" = (
"/data/2.5/weather?lat=&lon=&units=Metric%22"
);
} }
error parsing response from POST on /todos
Any ideas on how to get the temp from this API?
Here is my struct code:
struct Coordinate : Decodable {
let lat, lon : Double?
}
struct Weather : Decodable {
var id : Int?
var main, myDescription, icon : String?
enum CodingKeys : String, CodingKey {
case id = "id"
case main = "main"
case icon = "icon"
case myDescription = "description"
}
}
struct Sys : Decodable {
let type, id : Int?
let sunrise, sunset : Date?
let message : Double?
let country : String?
}
struct Main : Decodable {
let temp : Double?
}
struct MyWeather : Decodable {
let coord : Coordinate?
let cod, visibility, id : Int?
let name : String?
let base : String?
let weather : [Weather]?
let sys : Sys?
let main : Main?
let dt : Date?
}
I check your api in postman get this response
{
"coord": {
"lon": 90.36,
"lat": 23.79
},
"weather": [
{
"id": 721,
"main": "Haze",
"description": "haze",
"icon": "50d"
}
],
"base": "stations",
"main": {
"temp": 304.15,
"pressure": 1013,
"humidity": 62,
"temp_min": 304.15,
"temp_max": 304.15
},
"visibility": 3000,
"wind": {
"speed": 4.1,
"deg": 330
},
"clouds": {
"all": 20
},
"dt": 1540182600,
"sys": {
"type": 1,
"id": 7879,
"message": 0.0056,
"country": "BD",
"sunrise": 1540166342,
"sunset": 1540207601
},
"id": 1337178,
"name": "Dhaka District",
"cod": 200
}
this is your full API response model class used this code
struct MyWeather : Decodable {
let coord : Coordinate?
let weather : [Weather]?
let base : String?
let main : Main?
let visibility: Int?
let wind : Wind?
let clouds : Clouds?
let dt : Date?
let sys : Sys?
let id : Int?
let name : String?
let cod : Int?
}
struct Coordinate : Decodable {
let lat : Double?
let lon : Double?
}
struct Weather : Decodable {
var id : Int?
var main, myDescription, icon : String?
enum CodingKeys : String, CodingKey {
case id = "id"
case main = "main"
case icon = "icon"
case myDescription = "description"
}
}
struct Main : Decodable {
let temp : Double?
let pressure : Int?
let humidity : Int?
let temp_min : Double?
let temp_max : Double?
}
struct Wind : Decodable {
let speed : Double?
let deg : Int?
}
struct Clouds: Decodable {
let all : Int?
}
struct Sys : Decodable {
let type : Int?
let id : Int?
let message : Double?
let country : String?
let sunrise : Date?
let sunset : Date?
}
Your code is parsing the data. However, I noticed at the end of your URL units=Metric%22 which should just be units=Metric. Also, your lat and lon will be incorrect. lat=(currentLocation.coordinate.latitude) should be lat=\(currentLocation.coordinate.latitude) and same for lon.
I'm following https://developers.google.com/places/web-service/details this doc to add all the information about a place, and for example to add "geometry"
"geometry" : {
"location" : {
"lat" : -33.866651,
"lng" : 151.195827
},
i created this function in my class that work well
private let geometryKey = "geometry"
private let locationKey = "location"
private let latitudeKey = "lat"
private let longitudeKey = "lng"
class EClass: NSObject {
var location: CLLocationCoordinate2D?
init(placeInfo:[String: Any]) {
placeId = placeInfo["place_id"] as! String
// coordinates
if let g = placeInfo[geometryKey] as? [String:Any] {
if let l = g[locationKey] as? [String:Double] {
if let lat = l[latitudeKey], let lng = l[longitudeKey] {
location = CLLocationCoordinate2D.init(latitude: lat, longitude: lng)
}
}
}
}
but but i'm having difficulty adding "reviews"
"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
}
],
i tried to follow the same concept of the function i created for geometry like this
if let t = place.details?["reviews"] as? [String:Any] {
if let n = t["author_name"], let m = t["text"] {
Mylabel.text = "\(t)"
}
but is not working, i also tried to add a breakpoint and only the first line enters. What can i do? How can i create a build to show the review with a label or anything i need?
Take advantage of Codable in Swift 4. You can simply convert your JSON into a specific struct. e.g. Based on your JSON:
let json = """
{
"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
}
]
}
"""
You can convert it into a Response struct using the following code:
struct Response: Codable {
struct Review: Codable, CustomStringConvertible {
let text: String
let authorName: String
var description: String {
return "Review text: \(text) authorName: \(authorName)"
}
enum CodingKeys: String, CodingKey {
case text
case authorName = "author_name"
}
}
let reviews: [Review]
}
do {
if let data = json.data(using: .utf8) {
let decoder = JSONDecoder()
let decoded = try decoder.decode(Response.self, from: data)
print(decoded.reviews)
} else {
print("data is not available")
}
} catch (let e) {
print(e)
}
In your code t is not a Dictionary it is an Array instead. So try doing something like this. Rest of that you can change as per your logic.
if let t = place.details?["reviews"] as? [String:Any] {
for dic in t {
if let n = dic["author_name"], let m = dic["text"] {
Mylabel.text = "\(t)"
}
}
}
Yeah, but You can also try to make it like that:
struct reviews: Codable{
var reviews: [review]?
}
struct review: Codable{
var author_name: String?
var author_url: String?
var language: String?
var profile_photo_url: String?
var rating: Int?
var relative_time_description: String?
var text: String?
var time: Int?
}
And then:
if let dict = place.details?["reviews"] as? [String: Any],
let dataToDecode = dict.data(using: .utf8){
do{
let decodedReviews = try JSONDecoder().decode(reviews.self, from: dataToDecode)
// here you have decoded reviews in array
}catch let err{
print(err)
}
}
I created this class
import UIKit
import CoreLocation
private let geometryKey = "geometry"
private let locationKey = "location"
private let latitudeKey = "lat"
private let longitudeKey = "lng"
private let nameKey = "name"
private let openingHoursKey = "opening_hours"
private let openNowKey = "open_now"
private let vicinityKey = "vicinity"
private let typesKey = "types"
private let photosKey = "photos"
private let phoneNumberKey = "phoneNumber"
private let ratingKey = "rating"
private let priceLevelKey = "priceLevel"
private let websiteKey = "website"
class QPlace: NSObject {
var location: CLLocationCoordinate2D?
var name: String?
var photos: [QPhoto]?
var vicinity: String?
var isOpen: Bool?
var types: [String]?
var rating: Float?
var priceLevel: Int?
var website: String?
init(placeInfo:[String: Any]) {
// coordinates
if let g = placeInfo[geometryKey] as? [String:Any] {
if let l = g[locationKey] as? [String:Double] {
if let lat = l[latitudeKey], let lng = l[longitudeKey] {
location = CLLocationCoordinate2D.init(latitude: lat, longitude: lng)
}
}
}
// name
name = placeInfo[nameKey] as? String
// opening hours
if let oh = placeInfo[openingHoursKey] as? [String:Any] {
if let on = oh[openNowKey] as? Bool {
isOpen = on
}
}
// vicinity
vicinity = placeInfo[vicinityKey] as? String
// types
types = placeInfo[typesKey] as? [String]
// rating
rating = placeInfo[ratingKey] as? Float
//priceLevel
priceLevel = placeInfo[priceLevelKey] as? Int
website = placeInfo[websiteKey] as? String
// photos
photos = [QPhoto]()
if let ps = placeInfo[photosKey] as? [[String:Any]] {
for p in ps {
photos?.append(QPhoto.init(photoInfo: p))
}
}
}
func getDescription() -> String {
var s : [String] = []
if let types = types {
s.append("\(types.joined(separator: ", "))")
}
if let rating = rating {
s.append("Rating: \(rating)")
}
if let priceLevel = priceLevel {
s.append("PriceLevel: \(priceLevel)")
}
if let website = website {
s.append("\(website)")
}
if let isOpen = isOpen {
s.append(isOpen ? "OPEN NOW" : "CLOSED NOW")
}
if let vicinity = vicinity {
s.append("\(vicinity)")
}
return s.joined(separator: "\n")
}
func heightForComment(_ font: UIFont, width: CGFloat) -> CGFloat {
let desc = getDescription()
let rect = NSString(string: desc).boundingRect(with: CGSize(width: width, height: CGFloat(MAXFLOAT)), options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return ceil(rect.height)
}
}
to get the place's details that i'll show in a VC of my application by calling this function func getDescription() -> String { } but my problem and i don't know why (because i follow the documentation of google places API) is that the website and also the price level not working, so when in the viewController i call the function getDescription() it load all place's details which i added in that function, but not the website and the price level. What i did wrong? How can i adjust it?
UPDATE
https://developers.google.com/places/ios-api/place-details
static func getNearbyPlaces(by category:String, coordinates:CLLocationCoordinate2D, radius:Int, token: String?, completion: #escaping (QNearbyPlacesResponse?, Error?) -> Void) {
var params : [String : Any]
if let t = token {
params = [
"key" : AppDelegate.googlePlacesAPIKey,
"pagetoken" : t,
]
} else {
params = [
"key" : AppDelegate.googlePlacesAPIKey,
"radius" : radius,
"location" : "\(coordinates.latitude),\(coordinates.longitude)",
"type" : category.lowercased()
]
}
As per the Google Places API:
The key for price level is price_level but you have used priceLevel which might be why you are not seeing the prices
As for website I think it could be case that there is no data available for the property you have selected.