diff --git a/DZNPhotoPickerController.podspec b/DZNPhotoPickerController.podspec index 6b0e319c..b1227d15 100644 --- a/DZNPhotoPickerController.podspec +++ b/DZNPhotoPickerController.podspec @@ -1,4 +1,4 @@ -@version = "1.6.1" +@version = "1.6.5" Pod::Spec.new do |s| s.name = "DZNPhotoPickerController" @@ -9,7 +9,7 @@ Pod::Spec.new do |s| s.screenshots = "https://raw.githubusercontent.com/dzenbot/DZNPhotoPickerController/master/Docs/screenshots.png" s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { "Ignacio Romero Z." => "iromero@dzen.cl" } - + s.source = { :git => "https://github.com/dzenbot/UIPhotoPickerController.git", :tag => "v#{s.version}" } s.default_subspec = 'Core' @@ -19,7 +19,7 @@ Pod::Spec.new do |s| s.subspec 'Core' do |ss| ss.source_files = 'Source/Classes/Core/*.{h,m}' - ss.dependency 'SDWebImage', '3.7' + ss.dependency 'SDWebImage', '3.7.1' ss.dependency 'DZNEmptyDataSet', '1.3.3' ss.dependency 'MBProgressHUD', '0.9' @@ -40,5 +40,5 @@ Pod::Spec.new do |s| ss.source_files = 'Source/Classes/Editor/*.{h,m}', 'Source/Classes/Core/DZNPhotoPickerControllerConstants.{h,m}' end - + end diff --git a/Source/Classes/Core/DZNPhotoDisplayViewController.h b/Source/Classes/Core/DZNPhotoDisplayViewController.h index e6f529db..411438e8 100644 --- a/Source/Classes/Core/DZNPhotoDisplayViewController.h +++ b/Source/Classes/Core/DZNPhotoDisplayViewController.h @@ -30,5 +30,6 @@ Stops any loading HTTP request. */ - (void)stopLoadingRequest; +- (void)hideKeyboard; @end diff --git a/Source/Classes/Core/DZNPhotoDisplayViewController.m b/Source/Classes/Core/DZNPhotoDisplayViewController.m index efa6656a..7cf97569 100644 --- a/Source/Classes/Core/DZNPhotoDisplayViewController.m +++ b/Source/Classes/Core/DZNPhotoDisplayViewController.m @@ -53,6 +53,7 @@ @implementation DZNPhotoDisplayViewController @synthesize loadButton = _loadButton; @synthesize activityIndicator = _activityIndicator; @synthesize searchTimer = _searchTimer; +static bool showResult; - (instancetype)init { @@ -519,7 +520,11 @@ - (void)selectedItemAtIndexPath:(NSIndexPath *)indexPath [controller.activityIndicator startAnimating]; __weak DZNPhotoEditorViewController *_controller = controller; - + + // workaround for bug where image is blank when returning to the same image + // remove any previously cached image + [[SDImageCache sharedImageCache] removeImageForKey:[metadata.sourceURL absoluteString] fromDisk:NO]; + [controller.imageView sd_setImageWithPreviousCachedImageWithURL:metadata.sourceURL andPlaceholderImage:nil options:SDWebImageCacheMemoryOnly|SDWebImageProgressiveDownload|SDWebImageRetryFailed @@ -599,6 +604,9 @@ - (void)shouldSearchPhotos:(NSString *)keyword if ((_previousService != _selectedService || _searchBar.text != keyword) && keyword.length > 1) { _previousService = _selectedService; + showResult = YES; + [_searchBar becomeFirstResponder]; + [_searchBar resignFirstResponder]; [self resetPhotos]; [self searchPhotosWithKeyword:keyword]; } @@ -840,13 +848,22 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath - (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar { + showResult = NO; [self stopLoadingRequest]; return YES; } - (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar { - return YES; + if (showResult) { + return YES; + }else { + return NO; + } +} +- (void) hideKeyboard { + showResult = YES; + [_searchBar resignFirstResponder]; } - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText diff --git a/Source/Classes/Core/DZNPhotoPickerController.m b/Source/Classes/Core/DZNPhotoPickerController.m index 54c2c988..c0de1985 100644 --- a/Source/Classes/Core/DZNPhotoPickerController.m +++ b/Source/Classes/Core/DZNPhotoPickerController.m @@ -208,6 +208,7 @@ - (void)cancelPicker:(id)sender [controller stopLoadingRequest]; } + [controller hideKeyboard]; if (self.cancellationBlock) { self.cancellationBlock(self); return; @@ -215,7 +216,9 @@ - (void)cancelPicker:(id)sender if (self.delegate && [self.delegate respondsToSelector:@selector(photoPickerControllerDidCancel:)]) { [self.delegate photoPickerControllerDidCancel:self]; + [self dismissViewControllerAnimated:YES completion:nil]; } + } diff --git a/Source/Classes/Services/DZNPhotoServiceClient.m b/Source/Classes/Services/DZNPhotoServiceClient.m index 33b385c3..2ee585e1 100644 --- a/Source/Classes/Services/DZNPhotoServiceClient.m +++ b/Source/Classes/Services/DZNPhotoServiceClient.m @@ -30,15 +30,15 @@ - (instancetype)initWithService:(DZNPhotoPickerControllerServices)service subscr { self = [super initWithBaseURL:baseURLForService(service)]; if (self) { - + _service = service; _subscription = subscription; - + self.requestSerializer = [AFJSONRequestSerializer serializer]; self.responseSerializer = [AFHTTPResponseSerializer serializer]; - + [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES]; - + [self configureHTTPHeader]; } return self; @@ -47,24 +47,24 @@ - (instancetype)initWithService:(DZNPhotoPickerControllerServices)service subscr - (void)configureHTTPHeader { NSString *consumerKey = [self consumerKey]; - + if (!consumerKey) { return; } - + NSString *accessToken = [self accessToken]; - + // Add basic auth to Bing service if (self.service == DZNPhotoPickerControllerServiceBingImages) { - + //Bing requires basic auth with password and user name as the consumer key. [self.requestSerializer setAuthorizationHeaderFieldWithUsername:consumerKey password:consumerKey]; } else if (self.service == DZNPhotoPickerControllerServiceGettyImages) { - + // Getty Images requires authentification via the custom 'Api-Key' HTTP Header [self.requestSerializer setValue:consumerKey forHTTPHeaderField:@"Api-Key"]; - + if (accessToken) { // Getty Images requires basic auth with access token via the standard Authorization HTTP header as type Bearer. [self.requestSerializer setValue:[NSString stringWithFormat:@"Bearer %@", accessToken] forHTTPHeaderField:@"Authorization"]; @@ -93,19 +93,19 @@ - (NSString *)credentialIdentifier - (NSString *)accessToken { NSString *identifier = [self credentialIdentifier]; - + if (!identifier) { return nil; } - + AFOAuthCredential *credential = [AFOAuthCredential retrieveCredentialWithIdentifier:identifier]; - + // If still found but expired, the credential is deleted and returns nil if (credential.isExpired) { [AFOAuthCredential deleteCredentialWithIdentifier:identifier]; return nil; } - + return credential.accessToken; } @@ -119,16 +119,16 @@ - (NSDictionary *)tagsParamsWithKeyword:(NSString *)keyword NSAssert(keyword, @"'keyword' cannot be nil for %@", NSStringFromService(self.service)); NSAssert([self consumerKey], @"'consumerKey' cannot be nil for %@", NSStringFromService(self.service)); NSAssert([self consumerSecret], @"'consumerSecret' cannot be nil for %@", NSStringFromService(self.service)); - + NSMutableDictionary *params = [NSMutableDictionary new]; [params setObject:[self consumerKey] forKey:keyForAPIConsumerKey(self.service)]; [params setObject:keyword forKey:keyForSearchTag(self.service)]; - + if (self.service == DZNPhotoPickerControllerServiceFlickr) { [params setObject:tagSearchUrlPathForService(self.service) forKey:@"method"]; [params setObject:@"json" forKey:@"format"]; } - + return params; } @@ -140,27 +140,27 @@ - (NSDictionary *)photosParamsWithKeyword:(NSString *)keyword page:(NSInteger)pa if (isConsumerSecretRequiredForService(self.service)) { NSAssert([self consumerSecret], @"'consumerSecret' cannot be nil for %@", NSStringFromService(self.service)); } - + NSMutableDictionary *params = [NSMutableDictionary new]; - + if (isConsumerKeyInParametersRequiredForService(self.service)) { [params setObject:[self consumerKey] forKey:keyForAPIConsumerKey(self.service)]; } - + //Bing requires parameters to be wrapped in '' values. if (self.service == DZNPhotoPickerControllerServiceBingImages) { [params setObject:[NSString stringWithFormat:@"'%@'", keyword] forKey:keyForSearchTerm(self.service)]; } else { [params setObject:keyword forKey:keyForSearchTerm(self.service)]; } - + if (keyForSearchResultPerPage(self.service)) { [params setObject:@(resultPerPage) forKey:keyForSearchResultPerPage(self.service)]; } if (self.service == DZNPhotoPickerControllerService500px || self.service == DZNPhotoPickerControllerServiceFlickr || self.service == DZNPhotoPickerControllerServiceGettyImages) { [params setObject:@(page) forKey:@"page"]; } - + if (self.service == DZNPhotoPickerControllerService500px) { [params setObject:@[@(2),@(4)] forKey:@"image_size"]; @@ -171,6 +171,7 @@ - (NSDictionary *)photosParamsWithKeyword:(NSString *)keyword page:(NSInteger)pa [params setObject:photoSearchUrlPathForService(self.service) forKey:@"method"]; [params setObject:@"json" forKey:@"format"]; [params setObject:@"photos" forKey:@"media"]; + [params setObject:@"relevance" forKey:@"sort"]; [params setObject:@(YES) forKey:@"in_gallery"]; [params setObject:@(1) forKey:@"safe_search"]; [params setObject:@(1) forKey:@"content_type"]; @@ -185,7 +186,7 @@ - (NSDictionary *)photosParamsWithKeyword:(NSString *)keyword page:(NSInteger)pa else if (self.service == DZNPhotoPickerControllerServiceBingImages) { [params setObject:@"'Moderate'" forKey:@"Adult"]; - + //Default to size medium. Size Large causes some buggy behavior with download times. [params setObject:@"'Size:Medium'" forKey:@"ImageFilters"]; } @@ -195,23 +196,23 @@ - (NSDictionary *)photosParamsWithKeyword:(NSString *)keyword page:(NSInteger)pa [params setObject:@"photography" forKey:@"graphical_styles"]; [params setObject:@"true" forKey:@"exclude_nudity"]; } - + return params; } - (NSData *)processData:(NSData *)data { if (self.service == DZNPhotoPickerControllerServiceFlickr) { - + NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSString *responsePrefix = @"jsonFlickrApi("; - + if ([string rangeOfString:responsePrefix].location != NSNotFound) { string = [[string stringByReplacingOccurrencesOfString:responsePrefix withString:@""] stringByReplacingOccurrencesOfString:@")" withString:@""]; return [string dataUsingEncoding:NSUTF8StringEncoding]; } } - + return data; } @@ -219,20 +220,20 @@ - (NSArray *)parseObjects:(Class)class withJSON:(NSDictionary *)json { NSString *keyPath = keyPathForObjectName(self.service, [class name]); NSMutableArray *objects = [NSMutableArray arrayWithArray:[json valueForKeyPath:keyPath]]; - + if ([[class name] isEqualToString:[DZNPhotoTag name]]) { - + if (self.service == DZNPhotoPickerControllerServiceFlickr) { NSString *keyword = [json valueForKeyPath:@"tags.source"]; if (keyword) [objects insertObject:@{keyForSearchTagContent(self.service):keyword} atIndex:0]; } - + return [DZNPhotoTag photoTagListFromService:self.service withResponse:objects]; } else if ([[class name] isEqualToString:[DZNPhotoMetadata name]]) { return [DZNPhotoMetadata metadataListWithResponse:objects service:self.service]; } - + return nil; } @@ -242,10 +243,10 @@ - (NSArray *)parseObjects:(Class)class withJSON:(NSDictionary *)json - (void)setCredentialIdentifier:(NSString *)identifier service:(DZNPhotoPickerControllerServices)service { NSAssert(identifier, @"'identifier' cannot be nil"); - + [[NSUserDefaults standardUserDefaults] setObject:identifier forKey:NSUserDefaultsUniqueKey(service, DZNPhotoServiceCredentialIdentifier)]; [[NSUserDefaults standardUserDefaults] synchronize]; - + [self configureHTTPHeader]; } @@ -255,7 +256,7 @@ - (void)setCredentialIdentifier:(NSString *)identifier service:(DZNPhotoPickerCo - (void)searchTagsWithKeyword:(NSString *)keyword completion:(DZNHTTPRequestCompletion)completion { NSString *path = tagSearchUrlPathForService(self.service); - + NSDictionary *params = [self tagsParamsWithKeyword:keyword]; [self getObject:[DZNPhotoTag class] path:path params:params completion:completion]; } @@ -271,12 +272,12 @@ - (void)searchPhotosWithKeyword:(NSString *)keyword page:(NSInteger)page resultP - (void)getObject:(Class)class path:(NSString *)path params:(NSDictionary *)params completion:(DZNHTTPRequestCompletion)completion { _loading = YES; - + if (isAuthenticationRequiredForService(self.service) && ![self accessToken]) { [self authenticateWithClientKey:[self consumerKey] secret:[self consumerSecret] completion:^(NSString *accessToken, NSError *error) { - + if (!error) { [self getObject:class path:path params:params completion:completion]; } @@ -287,7 +288,7 @@ - (void)getObject:(Class)class path:(NSString *)path params:(NSDictionary *)para }]; return; } - + if (self.service == DZNPhotoPickerControllerServiceInstagram) { NSString *keyword = [params objectForKey:keyForSearchTerm(self.service)]; NSString *encodedKeyword = [keyword stringByReplacingOccurrencesOfString:@" " withString:@""]; @@ -296,18 +297,20 @@ - (void)getObject:(Class)class path:(NSString *)path params:(NSDictionary *)para else if (self.service == DZNPhotoPickerControllerServiceFlickr) { path = @""; } - + + NSLog(@"GET %@ %@", path, params); + [self GET:path parameters:params success:^(AFHTTPRequestOperation *operation, id response) { - + NSData *data = [self processData:response]; NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves | NSJSONReadingAllowFragments error:nil]; - + _loading = NO; if (completion) completion([self parseObjects:class withJSON:json], nil); - + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - + _loading = NO; if (completion) completion(nil, error); }]; @@ -325,15 +328,15 @@ - (void)authenticateWithClientKey:(NSString *)key secret:(NSString *)secret comp { NSURL *baseURL = baseURLForService(self.service); GROAuth2SessionManager *sessionManager = [GROAuth2SessionManager managerWithBaseURL:baseURL clientID:key secret:secret]; - + NSString *path = authUrlPathForService(self.service); - + NSDictionary *params = @{}; - + if (self.service == DZNPhotoPickerControllerServiceGettyImages) { params = @{@"grant_type":@"client_credentials"}; } - + [sessionManager authenticateUsingOAuthWithPath:path parameters:params success:^(AFOAuthCredential *credential) {