1
votes

I am trying to display photos of specific locations using a 'photo_reference' provided by Google's Places API.

Currently, I am using Google Places API's 'Place Details' requests to get information about specific locations but am having trouble displaying photos of those locations. Google provides a 'photo_reference' in the 'Place Details' response that is supposed to be used to get specific images but the documentation here isn't very helpful at showing how.

I'm currently making Google Place Details requests like this: (i have a function to create the url, then a function to make the request)

    func googlePlacesDetailsURL(forKey apiKey: String, place_ID: String) -> URL {
        print("passed  place_ID  before url creation ", place_ID)

        let baseURL = "https://maps.googleapis.com/maps/api/place/details/json?"
        let place_idString = "place_id=" + place_ID
        let fields = "fields=geometry,name,rating,price_level,types,opening_hours,formatted_address,formatted_phone_number,website,photos"
        let key = "key=" + apiKey

        print("Details request URL:", URL(string: baseURL + place_idString + "&" + fields + "&" + key)!)
        return URL(string: baseURL + place_idString + "&" + fields + "&" + key)!
    }


    func getGooglePlacesDetailsData(place_id: String, using completionHandler: @escaping (GooglePlacesDetailsResponse) -> ())  {

        let url = googlePlacesDetailsURL(forKey: googlePlacesKey, place_ID: place_id)

        let task = session.dataTask(with: url) { (responseData, _, error) in
            if let error = error {
                print(error.localizedDescription)
                return
            }

            guard let data = responseData, let detailsResponse = try? JSONDecoder().decode(GooglePlacesDetailsResponse.self, from: data) else {
                print("Could not decode JSON response. responseData was: ", responseData)
                return
            }
            print("GPD response - detailsResponse.result: ", detailsResponse.result)

                completionHandler(detailsResponse)

        }
        task.resume()

    }

Does anyone know how to make a Google Place Photo request using a 'photo_reference' in Swift, and display the returned photo?

2

2 Answers

1
votes

From what i understood it seems that you have to create a new URL using Photo_reference that is returned from the Place Search or Place Details request.

As you think the photo_reference is not an image , instead it is a Http reference that you can use to access the image ,Using that reference you will have to replace the below string and access that link to return an image

https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&photoreference=CnRtAAAATLZNl354RwP_9UKbQ_5Psy40texXePv4oAlgP4qNEkdIrkyse7rPXYGd9D_Uj1rVsQdWT4oRz4QrYAJNpFX7rzqqMlZw2h2E2y5IKMUZ7ouD_SlcHxYq1yL4KbKUv3qtWgTK0A6QbGh87GB3sscrHRIQiG2RrmU_jF4tENr9wGS_YxoUSSDrYjWmrNfeEHSGSc3FyhNLlBU&key=YOUR_API_KEY

The "Your_Api_Key" is obviously what it means , you have to access the returned photo reference and using replaceCharactersInRange and replace the "photoreference in the below link.

maxwidth can be defiend by you depending on what size image you require.

1
votes

I know i am very late to give the answer to this , sorry iv been real busy but i managed to get it done for you , This is just my take on it and i am still new to IOS as well so while my design might not be perfect i assure you that it works .One thing to keep in mind is not every place has a photo_reference so you will have to error handle that in case the image is assinged a nil value or when the URl is being created it will throw an exception, Take a look at the below code, i put it all in one method but its good if you can break it into a few methods to set the image and to fetch data . Get back to me with your feed back as i enjoyed studying this as well , Thank you and good Luck .

PS : This is in objective C so you got a little work to do sorry im not good with swift enough to produce this in it

-(void)fetchedData:(NSData *)responseData {
    //parse out the json data
    NSError* error;
    NSDictionary* json = [NSJSONSerialization
                          JSONObjectWithData:responseData

                          options:kNilOptions
                          error:&error];

    //Hardcoded placeId for testing purposes
    NSString *placeId = @"ChIJoS8a5GWM4kcRKOs9fcRijdk";

    //Filtered the json to access all the location Ids/place Ids
    NSArray *locations = [json valueForKeyPath:@"results.place_id"];

    //Iterator to iterate through the locations to see if the required place id is present in the Dictionary

    for (NSString *locationId in locations) {

        if ([placeId isEqualToString:locationId]){

            NSLog(@"Found The Matching LocationID");

            //predicate to iterate through all the places ids that match in order to access the entire object that has the location id so you can use it later onwards to access any part of the object (ratings, prices.... )
            NSPredicate *objectWithPlacesId = [NSPredicate predicateWithFormat:@"place_id == %@",locationId];

            //This array holds the entire object that contains the required place id
            NSArray *filteredArrayWithPlacesDetails = [[json objectForKey:@"results"] filteredArrayUsingPredicate:objectWithPlacesId];

            //Small question here if this is actually needed but i found it a problem to access the array as it returns a single object array
            NSDictionary *dictionaryWithDetails = [filteredArrayWithPlacesDetails firstObject];

            NSArray *photosArray = [dictionaryWithDetails valueForKeyPath:@"photos.photo_reference"];
            //NSString photo refence is accessed here , single object array so the first index always contain the photoReference
            NSString *photo_Reference = [photosArray objectAtIndex:0];

            //Create the Image Url , you can even format the max width and height the same way using %f
            NSString *imageUrl = [NSString stringWithFormat:@"https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&photoreference=%@&key=%@",photo_Reference,kGOOGLE_API_KEY];

            //Assing the image request for the sd_setImageWithURL to access the remote image
            [self.imageView sd_setImageWithURL:[NSURL URLWithString:imageUrl]
                              placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

            break;
        }

        else{
            NSLog(@"Not Matching");
        }



    }

}