diff --git a/FTGooglePlacesAPI/FTGooglePlacePhotoItem.h b/FTGooglePlacesAPI/FTGooglePlacePhotoItem.h new file mode 100644 index 0000000..48a30e6 --- /dev/null +++ b/FTGooglePlacesAPI/FTGooglePlacePhotoItem.h @@ -0,0 +1,22 @@ +// +// FTGooglePlacePhotoItem.h +// Aniways +// +// Created by Danny Shmueli on 5/15/14. +// Copyright (c) 2014 Ram Greenberg. All rights reserved. +// + +#import +@class UIImage; + +@interface FTGooglePlacePhotoItem : NSObject + +@property (nonatomic, strong) NSArray *htmlAttributions; +@property (nonatomic, copy) NSString *photoReference; +@property (nonatomic) NSInteger height, width; + +-(void)resolveImage:(void(^)(UIImage *))completion; + +-(id)initWithDictionary:(NSDictionary *)dictionary; + +@end diff --git a/FTGooglePlacesAPI/FTGooglePlacePhotoItem.m b/FTGooglePlacesAPI/FTGooglePlacePhotoItem.m new file mode 100644 index 0000000..e89ddbb --- /dev/null +++ b/FTGooglePlacesAPI/FTGooglePlacePhotoItem.m @@ -0,0 +1,39 @@ +// +// FTGooglePlacePhotoItem.m +// Aniways +// +// Created by Danny Shmueli on 5/15/14. +// Copyright (c) 2014 Ram Greenberg. All rights reserved. +// + +#import "FTGooglePlacePhotoItem.h" +#import "FTGooglePlacesAPIService.h" +#import "FTGooglePlacesAPIPhotoRequest.h" + +@implementation FTGooglePlacePhotoItem + +-(id)initWithDictionary:(NSDictionary *)dictionary +{ + self = [super init]; + if (!self) + return nil; + + self.photoReference = dictionary[@"photo_reference"]; + self.htmlAttributions = dictionary[@"html_attributions"]; + self.height = [[dictionary ftgp_nilledObjectForKey:@"height"] floatValue]; + self.width = [[dictionary ftgp_nilledObjectForKey:@"width"] floatValue]; + + return self; +} + +-(void)resolveImage:(void(^)(UIImage *))completion +{ + FTGooglePlacesAPIPhotoRequest *photoRequest =[[FTGooglePlacesAPIPhotoRequest alloc] initWithReference:self.photoReference maxWidth:@(1600) maxHeight:nil]; + + [FTGooglePlacesAPIService executePhotoRequest:photoRequest withCompletionHandler:^(UIImage *image, NSError *error) + { + completion(image); + }]; +} + +@end diff --git a/FTGooglePlacesAPI/FTGooglePlaceReviewItem.h b/FTGooglePlacesAPI/FTGooglePlaceReviewItem.h new file mode 100644 index 0000000..6ab681f --- /dev/null +++ b/FTGooglePlacesAPI/FTGooglePlaceReviewItem.h @@ -0,0 +1,20 @@ +// +// FTGooglePlaceReviewItem.h +// Aniways +// +// Created by Danny Shmueli on 5/15/14. +// Copyright (c) 2014 Ram Greenberg. All rights reserved. +// + +#import + +@interface FTGooglePlaceReviewItem : NSObject + +@property (nonatomic, copy) NSString *authorName, *authorURL, *reviewBody; +@property (nonatomic) float rating; +@property (nonatomic) NSInteger time; + + +-(id)initWithDictionary:(NSDictionary *)dictionary; + +@end diff --git a/FTGooglePlacesAPI/FTGooglePlaceReviewItem.m b/FTGooglePlacesAPI/FTGooglePlaceReviewItem.m new file mode 100644 index 0000000..6aa615d --- /dev/null +++ b/FTGooglePlacesAPI/FTGooglePlaceReviewItem.m @@ -0,0 +1,29 @@ +// +// FTGooglePlaceReviewItem.m +// Aniways +// +// Created by Danny Shmueli on 5/15/14. +// Copyright (c) 2014 Ram Greenberg. All rights reserved. +// + +#import "FTGooglePlaceReviewItem.h" +#import "FTGooglePlacesAPICommon.h" + +@implementation FTGooglePlaceReviewItem + +-(id)initWithDictionary:(NSDictionary *)dictionary +{ + self = [super init]; + if (!self) + return nil; + + self.authorName = [dictionary ftgp_nilledObjectForKey:@"author_name"]; + self.authorURL = [dictionary ftgp_nilledObjectForKey:@"author_url"]; + self.reviewBody = [dictionary ftgp_nilledObjectForKey:@"text"]; + self.rating = [[dictionary ftgp_nilledObjectForKey:@"rating"] doubleValue]; + self.time = [[dictionary ftgp_nilledObjectForKey:@"time"] doubleValue]; + + return self; +} + +@end diff --git a/FTGooglePlacesAPI/FTGooglePlacesAPICommon.h b/FTGooglePlacesAPI/FTGooglePlacesAPICommon.h index e409190..c890840 100644 --- a/FTGooglePlacesAPI/FTGooglePlacesAPICommon.h +++ b/FTGooglePlacesAPI/FTGooglePlacesAPICommon.h @@ -61,6 +61,14 @@ extern NSString * const FTGooglePlacesAPIErrorDomain; */ - (NSDictionary *)placesAPIRequestParams; +/** + * Most of the request are asking for JSON response from the API. + * Some requests - like GoogleAPIPhotoRequest do not. + * + * @return BOOL YES if the request requires JSON. + */ +- (BOOL)isJSONRequest; + @end // Utilities diff --git a/FTGooglePlacesAPI/FTGooglePlacesAPIDetailRequest.m b/FTGooglePlacesAPI/FTGooglePlacesAPIDetailRequest.m index 85c8bb4..cc65e41 100644 --- a/FTGooglePlacesAPI/FTGooglePlacesAPIDetailRequest.m +++ b/FTGooglePlacesAPI/FTGooglePlacesAPIDetailRequest.m @@ -67,4 +67,9 @@ - (NSDictionary *)placesAPIRequestParams return @{@"reference": _reference}; } +-(BOOL)isJSONRequest +{ + return YES; +} + @end diff --git a/FTGooglePlacesAPI/FTGooglePlacesAPIDetailResponse.h b/FTGooglePlacesAPI/FTGooglePlacesAPIDetailResponse.h index cf2059d..2d5bbb0 100644 --- a/FTGooglePlacesAPI/FTGooglePlacesAPIDetailResponse.h +++ b/FTGooglePlacesAPI/FTGooglePlacesAPIDetailResponse.h @@ -85,7 +85,9 @@ @property (nonatomic, strong, readonly) NSString *internationalPhoneNumber; @property (nonatomic, strong, readonly) NSString *iconImageUrl; -@property (nonatomic, assign, readonly) CGFloat rating; +@property (nonatomic, assign, readonly) float rating; +@property (nonatomic, strong) NSArray *photos; +@property (nonatomic, strong) NSArray *reviews; /** * Contains a unique token that you can use to retrieve additional information diff --git a/FTGooglePlacesAPI/FTGooglePlacesAPIDetailResponse.m b/FTGooglePlacesAPI/FTGooglePlacesAPIDetailResponse.m index c6f09ea..741e16d 100644 --- a/FTGooglePlacesAPI/FTGooglePlacesAPIDetailResponse.m +++ b/FTGooglePlacesAPI/FTGooglePlacesAPIDetailResponse.m @@ -31,6 +31,8 @@ #import "FTGooglePlacesAPIDetailResponse.h" #import "FTGooglePlacesAPICommon.h" +#import "FTGooglePlacePhotoItem.h" +#import "FTGooglePlaceReviewItem.h" @interface FTGooglePlacesAPIDetailResponse (Private) @@ -103,6 +105,29 @@ - (void)ftgp_importDictionary:(NSDictionary *)dictionary _websiteUrl = [NSURL URLWithString:[dictionary ftgp_nilledObjectForKey:@"website"]]; _utcOffset = [[dictionary ftgp_nilledObjectForKey:@"utc_offset"] doubleValue]; + + NSArray *photos = [dictionary ftgp_nilledObjectForKey:@"photos"]; + if (photos) + { + NSMutableArray *photosArray = [NSMutableArray arrayWithCapacity:photos.count]; + for (NSDictionary *photoDic in photos) { + + FTGooglePlacePhotoItem *photo = [[FTGooglePlacePhotoItem alloc] initWithDictionary:photoDic]; + [photosArray addObject:photo]; + } + _photos = photosArray; + } + + NSArray *reviews = [dictionary ftgp_nilledObjectForKey:@"reviews"]; + if (reviews) + { + NSMutableArray *reviewsArray = [NSMutableArray arrayWithCapacity:reviews.count]; + for (NSDictionary *reviewDic in reviews) { + FTGooglePlaceReviewItem *review = [[FTGooglePlaceReviewItem alloc] initWithDictionary: reviewDic]; + [reviewsArray addObject:review]; + } + _reviews = reviewsArray; + } } @end \ No newline at end of file diff --git a/FTGooglePlacesAPI/FTGooglePlacesAPIDictionaryRequest.m b/FTGooglePlacesAPI/FTGooglePlacesAPIDictionaryRequest.m index ade8173..507c4da 100644 --- a/FTGooglePlacesAPI/FTGooglePlacesAPIDictionaryRequest.m +++ b/FTGooglePlacesAPI/FTGooglePlacesAPIDictionaryRequest.m @@ -66,4 +66,9 @@ - (NSDictionary *)placesAPIRequestParams return _placesAPIRequestParams; } +-(BOOL)isJSONRequest +{ + return YES; +} + @end diff --git a/FTGooglePlacesAPI/FTGooglePlacesAPINearbySearchRequest.m b/FTGooglePlacesAPI/FTGooglePlacesAPINearbySearchRequest.m index 6a3fcc6..7563091 100644 --- a/FTGooglePlacesAPI/FTGooglePlacesAPINearbySearchRequest.m +++ b/FTGooglePlacesAPI/FTGooglePlacesAPINearbySearchRequest.m @@ -163,6 +163,11 @@ - (NSDictionary *)placesAPIRequestParams return [params copy]; } +-(BOOL)isJSONRequest +{ + return YES; +} + @end #pragma mark - Private methods category diff --git a/FTGooglePlacesAPI/FTGooglePlacesAPIPhotoRequest.h b/FTGooglePlacesAPI/FTGooglePlacesAPIPhotoRequest.h new file mode 100644 index 0000000..a19da99 --- /dev/null +++ b/FTGooglePlacesAPI/FTGooglePlacesAPIPhotoRequest.h @@ -0,0 +1,21 @@ +// +// FTGooglePlacesAPIPhotoRequest.h +// Aniways +// +// Created by Danny Shmueli on 5/16/14. +// Copyright (c) 2014 Ram Greenberg. All rights reserved. +// + +#import + +#import "FTGooglePlacesAPICommon.h" + +@interface FTGooglePlacesAPIPhotoRequest : NSObject + + +@property (nonatomic, copy, readonly) NSString *reference; +@property (nonatomic, strong, readonly) NSNumber *maxHeight, *maxWidth; + +- (instancetype)initWithReference:(NSString *)reference maxWidth:(NSNumber *)maxWidth maxHeight:(NSNumber *)maxHeight; + +@end diff --git a/FTGooglePlacesAPI/FTGooglePlacesAPIPhotoRequest.m b/FTGooglePlacesAPI/FTGooglePlacesAPIPhotoRequest.m new file mode 100644 index 0000000..0313cdc --- /dev/null +++ b/FTGooglePlacesAPI/FTGooglePlacesAPIPhotoRequest.m @@ -0,0 +1,60 @@ +// +// FTGooglePlacesAPIPhotoRequest.m +// Aniways +// +// Created by Danny Shmueli on 5/16/14. +// Copyright (c) 2014 Ram Greenberg. All rights reserved. +// + +#import "FTGooglePlacesAPIPhotoRequest.h" + +@implementation FTGooglePlacesAPIPhotoRequest + +- (instancetype)initWithReference:(NSString *)reference maxWidth:(NSNumber *)maxWidth maxHeight:(NSNumber *)maxHeight +{ + if ([reference length] == 0) { + NSLog(@"WARNING: Trying to create FTGooglePlacesAPIDetailRequest with empty reference. Returning nil"); + return nil; + } + + self = [super init]; + if (self) { + _reference = reference; + _maxHeight = maxHeight; + _maxWidth = maxWidth; + } + return self; +} + +#pragma mark - Superclass overrides + +- (NSString *)description +{ + return [NSString stringWithFormat:@"<%@: %p> Reference: %@", [self class], self, self.reference]; +} + +#pragma mark - FTGooglePlacesAPIRequest protocol + +- (NSString *)placesAPIRequestMethod +{ + return @"photo"; +} + +- (NSDictionary *)placesAPIRequestParams +{ + NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObject:self.reference forKey:@"photoreference"]; + if (self.maxHeight) + [params setObject:self.maxHeight forKey:@"maxheight"]; + + if (self.maxWidth) + [params setObject:self.maxWidth forKey:@"maxwidth"]; + + return params; +} + +-(BOOL)isJSONRequest +{ + return NO; +} + +@end diff --git a/FTGooglePlacesAPI/FTGooglePlacesAPISearchResultItem.h b/FTGooglePlacesAPI/FTGooglePlacesAPISearchResultItem.h index cdcbc0a..0d60f9b 100644 --- a/FTGooglePlacesAPI/FTGooglePlacesAPISearchResultItem.h +++ b/FTGooglePlacesAPI/FTGooglePlacesAPISearchResultItem.h @@ -50,12 +50,13 @@ typedef NS_ENUM(NSUInteger, FTGooglePlacesAPISearchResultItemOpenedState) { @property (nonatomic, strong, readonly) CLLocation *location; @property (nonatomic, strong, readonly) NSString *addressString; // "vicinity" from the response +@property (nonatomic, strong, readonly) NSString *formattedAddress; @property (nonatomic, assign, readonly) FTGooglePlacesAPISearchResultItemOpenedState openedState; @property (nonatomic, strong, readonly) NSString *iconImageUrl; -@property (nonatomic, assign, readonly) CGFloat rating; +@property (nonatomic, assign, readonly) float rating; @property (nonatomic, strong, readonly) NSString *reference; @property (nonatomic, strong, readonly) NSArray *types; - +@property (nonatomic, strong) NSArray *photos; /** * You can access complete response dictionary using this property. * In case implementation changes in a future and there will be new values diff --git a/FTGooglePlacesAPI/FTGooglePlacesAPISearchResultItem.m b/FTGooglePlacesAPI/FTGooglePlacesAPISearchResultItem.m index 4771d39..4a1490b 100644 --- a/FTGooglePlacesAPI/FTGooglePlacesAPISearchResultItem.m +++ b/FTGooglePlacesAPI/FTGooglePlacesAPISearchResultItem.m @@ -28,6 +28,7 @@ #import "FTGooglePlacesAPISearchResultItem.h" #import "FTGooglePlacesAPICommon.h" +#import "FTGooglePlacePhotoItem.h" /** * Private methods interface @@ -135,6 +136,7 @@ - (void)ftgpi_importDictionary:(NSDictionary *)dictionary } _addressString = [dictionary ftgp_nilledObjectForKey:@"vicinity"]; + _formattedAddress = [dictionary ftgp_nilledObjectForKey:@"formatted_address"]; // Openeed state may or may not be present NSNumber *openedState = [dictionary ftgp_nilledValueForKeyPath:@"opening_hours.open_now"]; @@ -148,6 +150,18 @@ - (void)ftgpi_importDictionary:(NSDictionary *)dictionary _rating = [[dictionary ftgp_nilledObjectForKey:@"rating"] floatValue]; _reference = [dictionary ftgp_nilledObjectForKey:@"reference"]; _types = [dictionary ftgp_nilledObjectForKey:@"types"]; + + NSArray *photos = [dictionary ftgp_nilledObjectForKey:@"photos"]; + if (photos) + { + NSMutableArray *photosArray = [NSMutableArray arrayWithCapacity:photos.count]; + for (NSDictionary *photoDic in photos) { + + FTGooglePlacePhotoItem *photo = [[FTGooglePlacePhotoItem alloc] initWithDictionary:photoDic]; + [photosArray addObject:photo]; + } + _photos = photosArray; + } } @end diff --git a/FTGooglePlacesAPI/FTGooglePlacesAPIService.h b/FTGooglePlacesAPI/FTGooglePlacesAPIService.h index efa1cb8..04df9b4 100644 --- a/FTGooglePlacesAPI/FTGooglePlacesAPIService.h +++ b/FTGooglePlacesAPI/FTGooglePlacesAPIService.h @@ -29,6 +29,7 @@ #import #import "FTGooglePlacesAPICommon.h" +@class UIImage; @class FTGooglePlacesAPISearchResponse; @class FTGooglePlacesAPIDetailResponse; @@ -39,6 +40,8 @@ typedef void (^FTGooglePlacesAPISearchRequestCompletionHandler)(FTGooglePlacesAP typedef void (^FTGooglePlacesAPIDetailRequestCompletionhandler)(FTGooglePlacesAPIDetailResponse *response, NSError *error); +typedef void (^FTGooglePlacesAPIPhotoRequestCompletionhandler)(UIImage *response, NSError *error); + /** * This class provides encapsulated functionality for communication with Google Places API */ @@ -86,6 +89,15 @@ typedef void (^FTGooglePlacesAPIDetailRequestCompletionhandler)(FTGooglePlacesAP + (void)executeDetailRequest:(id)request withCompletionHandler:(FTGooglePlacesAPIDetailRequestCompletionhandler)completion; +/** + * Asks the service to execute the given Google Places API Photo request. + * + * @param request Request object implementing FTGooglePlacesAPIRequest protocol. This will probably be instance of FTGooglePlacesAPIPhotoRequest, but you are free to provide own request implementing requred FTGooglePlacesAPIRequest protocol + * @param completion Completion block to be called after the request was finished. If everything went without problems, response will be non-nill and error will be nil. In case of failure, response will be nil and error will be either AFNetworking error caused by networking problem or error with FTGooglePlacesAPIErrorDomain domain indicating that the networking request was successfull, but Google Places API responded with non-OK status code + */ ++ (void)executePhotoRequest:(id)request + withCompletionHandler:(FTGooglePlacesAPIPhotoRequestCompletionhandler)completion; + /** * If set to YES and running in debug mode (#ifdef DEBUG), service will print some information * info console, including: diff --git a/FTGooglePlacesAPI/FTGooglePlacesAPIService.m b/FTGooglePlacesAPI/FTGooglePlacesAPIService.m index e131bca..2392482 100644 --- a/FTGooglePlacesAPI/FTGooglePlacesAPIService.m +++ b/FTGooglePlacesAPI/FTGooglePlacesAPIService.m @@ -209,6 +209,22 @@ + (void)executeDetailRequest:(id)request }]; } ++ (void)executePhotoRequest:(id)request + withCompletionHandler:(FTGooglePlacesAPIPhotoRequestCompletionhandler)completion +{ + [[self class] executeRequest:request withCompletionHandler:^(id responseObject, NSError *error) { + + // Networing, parsing or other general error + if (error) { + completion(nil, error); + return; + } + + completion(responseObject, nil); + }]; +} + + + (void)setDebugLoggingEnabled:(BOOL)enabled { FTGooglePlacesAPIDebugLoggingEnabled = enabled; @@ -236,11 +252,25 @@ + (void)executeRequest:(id)request // Create relative request path // Places API base URL is already configured in AFNetworking HTTP manager - NSString *requestPath = [NSString stringWithFormat:@"%@/json", [request placesAPIRequestMethod]]; - + NSString *requestPath = [request placesAPIRequestMethod]; + if ([request isJSONRequest]) + { + requestPath = [requestPath stringByAppendingString:@"/json"]; + } // Perform request using AFNetworking AFHTTPRequestOperationManager *manager = service.httpRequestOperationManager; + //Set the manager responseSerializer to AFImageResponseSerializer in case not JSON Request. + if ([request isJSONRequest]) + { + manager.responseSerializer = [AFJSONResponseSerializer serializer]; + } + else + { + manager.responseSerializer = [AFImageResponseSerializer serializer]; + } + + manager.requestSerializer.cachePolicy = NSURLRequestReturnCacheDataElseLoad; // Perform request [manager GET:requestPath parameters:params diff --git a/FTGooglePlacesAPI/FTGooglePlacesAPITextSearchRequest.m b/FTGooglePlacesAPI/FTGooglePlacesAPITextSearchRequest.m index c35ce6c..6ecb3d5 100644 --- a/FTGooglePlacesAPI/FTGooglePlacesAPITextSearchRequest.m +++ b/FTGooglePlacesAPI/FTGooglePlacesAPITextSearchRequest.m @@ -149,4 +149,8 @@ - (NSDictionary *)placesAPIRequestParams return [params copy]; } +-(BOOL)isJSONRequest +{ + return YES; +} @end