From ff96e240022163b6bef422637bfb66e2d564873f Mon Sep 17 00:00:00 2001 From: Paul Roub Date: Wed, 23 Aug 2017 17:25:46 -0400 Subject: [PATCH] resolve deprecation and other warnings per Xcode 8 rm unneeded (now incorrect) orientation checks; corrected todo-txt web address in Settings page Xcode 9 warning/deprecation resolution fix more deprecation warnings Update Pickers library From https://github.com/skywinder/ActionSheetPicker-3.0, the fork recommended by the original author --- Classes/ByTextFilter.m | 2 +- Classes/DropboxRemoteClient.h | 2 +- Classes/RelativeDate.m | 4 +- Classes/Task.h | 2 + Classes/TaskBagImpl.m | 2 +- Libraries/DDFileReader/DDFileReader.m | 11 +- .../IASKAppSettingsViewController.m | 29 +- .../IASKAppSettingsWebViewController.m | 6 +- .../IASKSpecifierValuesViewController.m | 15 +- .../Models/IASKSettingsReader.m | 18 +- .../Models/IASKSettingsStoreFile.m | 6 +- .../Models/IASKSettingsStoreUserDefaults.m | 2 +- .../InAppSettingsKit/Models/IASKSpecifier.m | 6 +- .../Views/IASKPSSliderSpecifierViewCell.m | 2 + Libraries/InAppSettingsKit/Views/IASKSlider.m | 3 +- Libraries/InAppSettingsKit/Views/IASKSwitch.m | 3 +- .../InAppSettingsKit/Views/IASKTextField.m | 3 +- .../Xibs/IASKAppSettingsView.xib | 293 ++------- Libraries/MBProgressHUD/MBProgressHUD.m | 7 +- Libraries/Pickers/AbstractActionSheetPicker.h | 100 +++- Libraries/Pickers/AbstractActionSheetPicker.m | 561 ++++++++++++------ Libraries/Pickers/ActionSheetCustomPicker.h | 8 +- Libraries/Pickers/ActionSheetCustomPicker.m | 14 +- Libraries/Pickers/ActionSheetDatePicker.h | 52 +- Libraries/Pickers/ActionSheetDatePicker.m | 136 ++++- Libraries/Pickers/ActionSheetDistancePicker.h | 8 +- Libraries/Pickers/ActionSheetDistancePicker.m | 30 +- Libraries/Pickers/ActionSheetLocalePicker.m | 45 +- .../Pickers/ActionSheetMultipleStringPicker.h | 65 ++ .../Pickers/ActionSheetMultipleStringPicker.m | 199 +++++++ Libraries/Pickers/ActionSheetPicker.h | 35 ++ Libraries/Pickers/ActionSheetStringPicker.m | 51 +- Libraries/Pickers/DistancePickerView.m | 2 +- Libraries/Pickers/SWActionSheet.h | 2 +- Libraries/Pickers/SWActionSheet.m | 68 ++- Libraries/SSTextView/SSTextView.m | 4 +- Protocols/TaskBag.h | 2 +- .../Todo-txt-unit-tests-Info.plist | 2 +- View Controllers/TaskEditViewController.m | 16 +- View Controllers/TasksViewController.m | 2 +- Views/TaskCell.m | 2 +- todo.txt-touch-ios.xcodeproj/project.pbxproj | 133 ++++- todo_txt_touch_ios-Info.plist | 2 +- 43 files changed, 1341 insertions(+), 614 deletions(-) create mode 100644 Libraries/Pickers/ActionSheetMultipleStringPicker.h create mode 100644 Libraries/Pickers/ActionSheetMultipleStringPicker.m create mode 100644 Libraries/Pickers/ActionSheetPicker.h diff --git a/Classes/ByTextFilter.m b/Classes/ByTextFilter.m index 34aff3c..8850cd7 100644 --- a/Classes/ByTextFilter.m +++ b/Classes/ByTextFilter.m @@ -42,7 +42,7 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#import "ByTextFIlter.h" +#import "ByTextFilter.h" #import "Task.h" @implementation ByTextFilter diff --git a/Classes/DropboxRemoteClient.h b/Classes/DropboxRemoteClient.h index fb6d650..8b996c4 100644 --- a/Classes/DropboxRemoteClient.h +++ b/Classes/DropboxRemoteClient.h @@ -44,7 +44,7 @@ #import #import "RemoteClient.h" #import -#import "DropboxFIleDownloader.h" +#import "DropboxFileDownloader.h" #import "DropboxFileUploader.h" @interface DropboxRemoteClient : NSObject diff --git a/Classes/RelativeDate.m b/Classes/RelativeDate.m index 6acafb1..6f609b1 100644 --- a/Classes/RelativeDate.m +++ b/Classes/RelativeDate.m @@ -92,8 +92,8 @@ + (NSString*)stringWithDate:(NSDate*)date fromDate:(NSDate*)fromDate withFormat: + (NSString*)stringWithDate:(NSDate*)date withFormat:(NSString*)format { NSDate* today = [NSDate date]; - NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; - NSDateComponents * comp = [cal components:( NSYearCalendarUnit| NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:today]; + NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; + NSDateComponents * comp = [cal components:( NSCalendarUnitYear| NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:today]; today = [cal dateFromComponents:comp]; return [RelativeDate stringWithDate:date fromDate:today withFormat:format]; diff --git a/Classes/Task.h b/Classes/Task.h index 0466196..92e7569 100644 --- a/Classes/Task.h +++ b/Classes/Task.h @@ -91,6 +91,8 @@ - (NSComparisonResult) compareByIdDescending:(Task*)other; - (NSComparisonResult) compareByPriority:(Task*)other; - (NSComparisonResult) compareByTextAscending:(Task*)other; +- (NSComparisonResult) compareByDateAscending:(Task*)other; +- (NSComparisonResult) compareByDateDescending:(Task*)other; - (NSArray *)rangesOfContexts:(NSString *)taskText; - (NSArray *)rangesOfProjects:(NSString *)taskText; diff --git a/Classes/TaskBagImpl.m b/Classes/TaskBagImpl.m index b62c346..b97c77c 100644 --- a/Classes/TaskBagImpl.m +++ b/Classes/TaskBagImpl.m @@ -222,7 +222,7 @@ - (NSArray*) tasksWithFilter:(id)filter withSortOrder:(Sort*)sortOrder { return localTasks; } -- (int) size { +- (NSUInteger) size { return [self.tasks count]; } diff --git a/Libraries/DDFileReader/DDFileReader.m b/Libraries/DDFileReader/DDFileReader.m index 817b43c..3d19cf3 100644 --- a/Libraries/DDFileReader/DDFileReader.m +++ b/Libraries/DDFileReader/DDFileReader.m @@ -67,9 +67,12 @@ - (id) initWithFilePath:(NSString *)aPath { - (void) dealloc { [fileHandle closeFile]; - [fileHandle release], fileHandle = nil; - [filePath release], filePath = nil; - [lineDelimiter release], lineDelimiter = nil; + [fileHandle release]; + fileHandle = nil; + [filePath release]; + filePath = nil; + [lineDelimiter release]; + lineDelimiter = nil; currentOffset = 0ULL; [super dealloc]; } @@ -117,4 +120,4 @@ - (void) enumerateLinesUsingBlock:(void(^)(NSString*, BOOL*))block { } #endif -@end \ No newline at end of file +@end diff --git a/Libraries/InAppSettingsKit/Controllers/IASKAppSettingsViewController.m b/Libraries/InAppSettingsKit/Controllers/IASKAppSettingsViewController.m index 6f1660c..7bd086f 100644 --- a/Libraries/InAppSettingsKit/Controllers/IASKAppSettingsViewController.m +++ b/Libraries/InAppSettingsKit/Controllers/IASKAppSettingsViewController.m @@ -105,6 +105,8 @@ - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil } - (void)awakeFromNib { + [super awakeFromNib]; + // If set to YES, will display credits for InAppSettingsKit creators _showCreditsFooter = NO; @@ -207,12 +209,18 @@ - (void)navigationController:(UINavigationController *)navigationController will - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - [_viewList release], _viewList = nil; - [_currentIndexPath release], _currentIndexPath = nil; - [_file release], _file = nil; - [_currentFirstResponder release], _currentFirstResponder = nil; - [_settingsReader release], _settingsReader = nil; - [_settingsStore release], _settingsStore = nil; + [_viewList release]; + _viewList = nil; + [_currentIndexPath release]; + _currentIndexPath = nil; + [_file release]; + _file = nil; + [_currentFirstResponder release]; + _currentFirstResponder = nil; + [_settingsReader release]; + _settingsReader = nil; + [_settingsStore release]; + _settingsStore = nil; _delegate = nil; @@ -319,10 +327,11 @@ - (CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger } NSString *title; if ((title = [self tableView:tableView titleForHeaderInSection:section])) { - CGSize size = [title sizeWithFont:[UIFont boldSystemFontOfSize:[UIFont labelFontSize]] - constrainedToSize:CGSizeMake(tableView.frame.size.width - 2*kIASKHorizontalPaddingGroupTitles, INFINITY) - lineBreakMode:NSLineBreakByWordWrapping]; - return size.height+kIASKVerticalPaddingGroupTitles; + CGRect rect = [title boundingRectWithSize:CGSizeMake(tableView.frame.size.width - 2*kIASKHorizontalPaddingGroupTitles, INFINITY) + options:NSStringDrawingUsesLineFragmentOrigin + attributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:[UIFont labelFontSize]] } + context:nil]; + return rect.size.height+kIASKVerticalPaddingGroupTitles; } return 0; } diff --git a/Libraries/InAppSettingsKit/Controllers/IASKAppSettingsWebViewController.m b/Libraries/InAppSettingsKit/Controllers/IASKAppSettingsWebViewController.m index f03c3da..c7fd244 100644 --- a/Libraries/InAppSettingsKit/Controllers/IASKAppSettingsWebViewController.m +++ b/Libraries/InAppSettingsKit/Controllers/IASKAppSettingsWebViewController.m @@ -39,8 +39,10 @@ - (id)initWithFile:(NSString*)urlString key:(NSString*)key { - (void)dealloc { - [webView release], webView = nil; - [url release], url = nil; + [webView release]; + webView = nil; + [url release]; + url = nil; [super dealloc]; } diff --git a/Libraries/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m b/Libraries/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m index b284eb2..eb33757 100644 --- a/Libraries/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m +++ b/Libraries/InAppSettingsKit/Controllers/IASKSpecifierValuesViewController.m @@ -101,11 +101,16 @@ - (void)viewDidUnload { - (void)dealloc { - [_currentSpecifier release], _currentSpecifier = nil; - [_checkedItem release], _checkedItem = nil; - [_settingsReader release], _settingsReader = nil; - [_settingsStore release], _settingsStore = nil; - [_tableView release], _tableView = nil; + [_currentSpecifier release]; + _currentSpecifier = nil; + [_checkedItem release]; + _checkedItem = nil; + [_settingsReader release]; + _settingsReader = nil; + [_settingsStore release]; + _settingsStore = nil; + [_tableView release]; + _tableView = nil; [super dealloc]; } diff --git a/Libraries/InAppSettingsKit/Models/IASKSettingsReader.m b/Libraries/InAppSettingsKit/Models/IASKSettingsReader.m index 3d1e5f9..6f4c75d 100644 --- a/Libraries/InAppSettingsKit/Models/IASKSettingsReader.m +++ b/Libraries/InAppSettingsKit/Models/IASKSettingsReader.m @@ -69,12 +69,18 @@ - (id)initWithFile:(NSString*)file { } - (void)dealloc { - [_path release], _path = nil; - [_localizationTable release], _localizationTable = nil; - [_bundlePath release], _bundlePath = nil; - [_settingsBundle release], _settingsBundle = nil; - [_dataSource release], _dataSource = nil; - [_bundle release], _bundle = nil; + [_path release]; + _path = nil; + [_localizationTable release]; + _localizationTable = nil; + [_bundlePath release]; + _bundlePath = nil; + [_settingsBundle release]; + _settingsBundle = nil; + [_dataSource release]; + _dataSource = nil; + [_bundle release]; + _bundle = nil; [super dealloc]; } diff --git a/Libraries/InAppSettingsKit/Models/IASKSettingsStoreFile.m b/Libraries/InAppSettingsKit/Models/IASKSettingsStoreFile.m index 104642d..c932c16 100644 --- a/Libraries/InAppSettingsKit/Models/IASKSettingsStoreFile.m +++ b/Libraries/InAppSettingsKit/Models/IASKSettingsStoreFile.m @@ -32,8 +32,10 @@ - (id)initWithPath:(NSString*)path { } - (void)dealloc { - [_dict release], _dict = nil; - [_filePath release], _filePath = nil; + [_dict release]; + _dict = nil; + [_filePath release]; + _filePath = nil; [super dealloc]; } diff --git a/Libraries/InAppSettingsKit/Models/IASKSettingsStoreUserDefaults.m b/Libraries/InAppSettingsKit/Models/IASKSettingsStoreUserDefaults.m index fd24bf0..8b85b3c 100644 --- a/Libraries/InAppSettingsKit/Models/IASKSettingsStoreUserDefaults.m +++ b/Libraries/InAppSettingsKit/Models/IASKSettingsStoreUserDefaults.m @@ -53,7 +53,7 @@ - (double)doubleForKey:(NSString*)key { } - (int)integerForKey:(NSString*)key { - return [[NSUserDefaults standardUserDefaults] integerForKey:key]; + return (int)[[NSUserDefaults standardUserDefaults] integerForKey:key]; } - (id)objectForKey:(NSString*)key { diff --git a/Libraries/InAppSettingsKit/Models/IASKSpecifier.m b/Libraries/InAppSettingsKit/Models/IASKSpecifier.m index b948509..461e05e 100644 --- a/Libraries/InAppSettingsKit/Models/IASKSpecifier.m +++ b/Libraries/InAppSettingsKit/Models/IASKSpecifier.m @@ -41,8 +41,10 @@ - (id)initWithSpecifier:(NSDictionary*)specifier { } - (void)dealloc { - [_specifierDict release], _specifierDict = nil; - [_multipleValuesDict release], _multipleValuesDict = nil; + [_specifierDict release]; + _specifierDict = nil; + [_multipleValuesDict release]; + _multipleValuesDict = nil; _settingsReader = nil; diff --git a/Libraries/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.m b/Libraries/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.m index cbdca02..423a548 100644 --- a/Libraries/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.m +++ b/Libraries/InAppSettingsKit/Views/IASKPSSliderSpecifierViewCell.m @@ -66,6 +66,8 @@ - (void)dealloc { } - (void)prepareForReuse { + [super prepareForReuse]; + _minImage.image = nil; _maxImage.image = nil; } diff --git a/Libraries/InAppSettingsKit/Views/IASKSlider.m b/Libraries/InAppSettingsKit/Views/IASKSlider.m index d591ff2..d6e7901 100644 --- a/Libraries/InAppSettingsKit/Views/IASKSlider.m +++ b/Libraries/InAppSettingsKit/Views/IASKSlider.m @@ -22,7 +22,8 @@ @implementation IASKSlider @synthesize key=_key; - (void)dealloc { - [_key release], _key = nil; + [_key release]; + _key = nil; [super dealloc]; } diff --git a/Libraries/InAppSettingsKit/Views/IASKSwitch.m b/Libraries/InAppSettingsKit/Views/IASKSwitch.m index f32aba4..2defb9a 100644 --- a/Libraries/InAppSettingsKit/Views/IASKSwitch.m +++ b/Libraries/InAppSettingsKit/Views/IASKSwitch.m @@ -22,7 +22,8 @@ @implementation IASKSwitch @synthesize key=_key; - (void)dealloc { - [_key release], _key = nil; + [_key release]; + _key = nil; [super dealloc]; } diff --git a/Libraries/InAppSettingsKit/Views/IASKTextField.m b/Libraries/InAppSettingsKit/Views/IASKTextField.m index 9056896..2bd1af3 100644 --- a/Libraries/InAppSettingsKit/Views/IASKTextField.m +++ b/Libraries/InAppSettingsKit/Views/IASKTextField.m @@ -22,7 +22,8 @@ @implementation IASKTextField @synthesize key=_key; - (void)dealloc { - [_key release], _key = nil; + [_key release]; + _key = nil; [super dealloc]; } diff --git a/Libraries/InAppSettingsKit/Xibs/IASKAppSettingsView.xib b/Libraries/InAppSettingsKit/Xibs/IASKAppSettingsView.xib index f3d480c..3b606c4 100644 --- a/Libraries/InAppSettingsKit/Xibs/IASKAppSettingsView.xib +++ b/Libraries/InAppSettingsKit/Xibs/IASKAppSettingsView.xib @@ -1,260 +1,35 @@ - - - 1280 - 10K549 - 1938 - 1038.36 - 461.00 - - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - 933 - - - YES - IBProxyObject - IBUITableView - - - YES - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - PluginDependencyRecalculationVersion - - - - YES - - IBFilesOwner - IBCocoaTouchFramework - - - IBFirstResponder - IBCocoaTouchFramework - - - - 274 - {320, 460} - - - - 10 - - 549453824 - {512, 1} - - YES - - YES - - - - TU0AKgAACAjFzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/ -y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/ -xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/ -xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/ -xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/ -xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/ -xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/ -y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/ -y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/ -xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/ -xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/ -xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/ -xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/ -xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/ -y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/ -y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/ -xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/ -xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/ -xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/ -xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/ -xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/ -y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/ -y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/ -xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/ -xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/ -xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/ -xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/ -xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/ -y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/ -y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/ -xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/ -xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/ -xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/ -xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/ -xczS/8vS2P/L0tj/xczU/wANAQAAAwAAAAECAAAAAQEAAwAAAAEAAQAAAQIAAwAAAAQAAAiqAQMAAwAA -AAEAAQAAAQYAAwAAAAEAAgAAAREABAAAAAEAAAAIARIAAwAAAAEAAQAAARUAAwAAAAEABAAAARYAAwAA -AAEAAQAAARcABAAAAAEAAAgAARwAAwAAAAEAAQAAAVIAAwAAAAEAAQAAAVMAAwAAAAQAAAiyAAAAAAAI -AAgACAAIAAEAAQABAAE - - - - - - 3 - MCAwAA - - - groupTableViewBackgroundColor - - NO - YES - NO - IBCocoaTouchFramework - NO - 1 - 2 - 0 - YES - 44 - 10 - 10 - - - - - YES - - - view - - - - 10 - - - - dataSource - - - - 6 - - - - delegate - - - - 7 - - - - - YES - - 0 - - YES - - - - - - -1 - - - File's Owner - - - -2 - - - - - 4 - - - - - - - YES - - YES - -1.CustomClassName - -1.IBPluginDependency - -2.CustomClassName - -2.IBPluginDependency - 4.IBPluginDependency - - - YES - IASKAppSettingsViewController - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - UIResponder - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - com.apple.InterfaceBuilder.IBCocoaTouchPlugin - - - - YES - - - - - - YES - - - - - 10 - - - - YES - - IASKAppSettingsViewController - UITableViewController - - dismiss: - id - - - dismiss: - - dismiss: - id - - - - delegate - id - - - delegate - - delegate - id - - - - IBProjectSource - ./Classes/IASKAppSettingsViewController.h - - - - - 0 - IBCocoaTouchFramework - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS - - - - com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 - - - YES - 3 - 933 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Libraries/MBProgressHUD/MBProgressHUD.m b/Libraries/MBProgressHUD/MBProgressHUD.m index 413609c..81e1cb6 100644 --- a/Libraries/MBProgressHUD/MBProgressHUD.m +++ b/Libraries/MBProgressHUD/MBProgressHUD.m @@ -19,12 +19,9 @@ - (void)handleGraceTimer:(NSTimer *)theTimer; - (void)handleMinShowTimer:(NSTimer *)theTimer; - (void)setTransformForCurrentOrientation:(BOOL)animated; - (void)cleanUp; -- (void)deviceOrientationDidChange:(NSNotification*)notification; - (void)launchExecution; - (void)deviceOrientationDidChange:(NSNotification *)notification; - (void)hideDelayed:(NSNumber *)animated; -- (void)launchExecution; -- (void)cleanUp; @property (retain) UIView *indicator; @property (assign) float width; @@ -319,7 +316,7 @@ - (void)layoutSubviews { // Add label if label text was set if (nil != self.labelText) { // Get size of label text - CGSize dims = [self.labelText sizeWithFont:self.labelFont]; + CGSize dims = [self.labelText sizeWithAttributes:@{ NSFontAttributeName: self.labelFont }]; // Compute label dimensions based on font metrics if size is larger than max then clip the label width float lHeight = dims.height; @@ -361,7 +358,7 @@ - (void)layoutSubviews { // Add details label delatils text was set if (nil != self.detailsLabelText) { // Get size of label text - dims = [self.detailsLabelText sizeWithFont:self.detailsLabelFont]; + dims = [self.detailsLabelText sizeWithAttributes:@{ NSFontAttributeName: self.detailsLabelFont }]; // Compute label dimensions based on font metrics if size is larger than max then clip the label width lHeight = dims.height; diff --git a/Libraries/Pickers/AbstractActionSheetPicker.h b/Libraries/Pickers/AbstractActionSheetPicker.h index 7c267ed..f4a88e4 100755 --- a/Libraries/Pickers/AbstractActionSheetPicker.h +++ b/Libraries/Pickers/AbstractActionSheetPicker.h @@ -28,50 +28,98 @@ #import #import +@class SWActionSheet; + +#define SuppressPerformSelectorLeakWarning(Stuff) \ +do { \ +_Pragma("clang diagnostic push") \ +_Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \ +Stuff; \ +_Pragma("clang diagnostic pop") \ +} while (0) + +typedef NS_ENUM(NSInteger, ActionType) { + ActionTypeValue, + ActionTypeSelector, + ActionTypeBlock +}; + +typedef NS_ENUM(NSInteger, TapAction) { + TapActionNone, + TapActionSuccess, + TapActionCancel +}; + +typedef void (^ActionBlock)(void); static NSString *const kButtonValue = @"buttonValue"; static NSString *const kButtonTitle = @"buttonTitle"; -@interface AbstractActionSheetPicker : NSObject -@property (nonatomic, strong) UIToolbar* toolbar; -@property (nonatomic, copy) NSString *title; -@property (nonatomic, strong) UIView *pickerView; -@property (nonatomic, readonly) CGSize viewSize; -@property (nonatomic, strong) NSMutableArray *customButtons; -@property (nonatomic, assign) BOOL hideCancel; -@property (nonatomic, assign) CGRect presentFromRect; -@property (nonatomic) NSDictionary *titleTextAttributes; // default is nil. Used to specify Title Label attributes. -@property (nonatomic) NSAttributedString *attributedTitle; // default is nil. If titleTextAttributes not nil this value ignorred. - - // For subclasses. -- (id)initWithTarget:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin; - - // Present the ActionSheetPicker +static NSString *const kActionType = @"buttonAction"; + +static NSString *const kActionTarget = @"buttonActionTarget"; + +@interface AbstractActionSheetPicker : NSObject +@property(nonatomic, strong) SWActionSheet *actionSheet; +@property(nonatomic, assign) NSInteger tag; +@property(nonatomic, assign) int borderWidth; +@property(nonatomic, strong) UIToolbar *toolbar; +@property(nonatomic, copy) NSString *title; +@property(nonatomic, strong) UIView *pickerView; +@property(nonatomic, readonly) CGSize viewSize; +@property(nonatomic, strong) NSMutableArray *customButtons; +@property(nonatomic, assign) BOOL hideCancel; // show or hide cancel button. +@property(nonatomic, assign) CGRect presentFromRect; +@property(nonatomic) NSDictionary *titleTextAttributes; // default is nil. Used to specify Title Label attributes. +@property(nonatomic) NSAttributedString *attributedTitle; // default is nil. If titleTextAttributes not nil this value ignored. +@property(nonatomic) NSMutableDictionary *pickerTextAttributes; // default with a NSMutableParagraphStyle to set label align center. Used to specify Picker Label attributes. +@property(nonatomic) UIColor *pickerBackgroundColor; +@property(nonatomic) UIColor *toolbarBackgroundColor; +@property(nonatomic, strong) UIColor *toolbarButtonsColor; +@property(nonatomic) NSNumber *pickerBlurRadius; +@property(nonatomic, retain) Class popoverBackgroundViewClass; //allow popover customization on iPad +@property(nonatomic) UIInterfaceOrientationMask supportedInterfaceOrientations; // You can set your own supportedInterfaceOrientations value to prevent dismissing picker in some special cases. +@property(nonatomic) TapAction tapDismissAction; // Specify, which action should be fired in case of tapping outside of the picker (on top darkened side). Default is TapActionNone. +@property(nonatomic) BOOL popoverDisabled; // Disable popover behavior on iPad + + +- (void)setTextColor:(UIColor *)textColor; + +// For subclasses. +- (instancetype)initWithTarget:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin; + +// Present the ActionSheetPicker - (void)showActionSheetPicker; - // For subclasses. This is used to send a message to the target upon a successful selection and dismissal of the picker (i.e. not canceled). +// For subclasses. This is used to send a message to the target upon a successful selection and dismissal of the picker (i.e. not canceled). - (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin; - // For subclasses. This is an optional message upon cancelation of the picker. +// For subclasses. This is an optional message upon cancelation of the picker. - (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin; - // For subclasses. This returns a configured picker view. Subclasses should autorelease. +// For subclasses. This returns a configured picker view. Subclasses should autorelease. - (UIView *)configuredPickerView; - // Adds custom buttons to the left of the UIToolbar that select specified values +// Adds custom buttons to the left of the UIToolbar that select specified values - (void)addCustomButtonWithTitle:(NSString *)title value:(id)value; - //For subclasses. This responds to a custom button being pressed. +// Adds custom buttons to the left of the UIToolbar that implement specified block +- (void)addCustomButtonWithTitle:(NSString *)title actionBlock:(ActionBlock)block; + +// Adds custom buttons to the left of the UIToolbar that implement specified selector +- (void)addCustomButtonWithTitle:(NSString *)title target:(id)target selector:(SEL)selector; + +//For subclasses. This responds to a custom button being pressed. - (IBAction)customButtonPressed:(id)sender; - // Allow the user to specify a custom cancel button -- (void) setCancelButton: (UIBarButtonItem *)button; +// Allow the user to specify a custom cancel button +- (void)setCancelButton:(UIBarButtonItem *)button; - // Allow the user to specify a custom done button -- (void) setDoneButton: (UIBarButtonItem *)button; +// Allow the user to specify a custom done button +- (void)setDoneButton:(UIBarButtonItem *)button; - // Hide picker programmatically -- (void) hidePickerWithCancelAction; +// Hide picker programmatically +- (void)hidePickerWithCancelAction; @end diff --git a/Libraries/Pickers/AbstractActionSheetPicker.m b/Libraries/Pickers/AbstractActionSheetPicker.m index b8bec28..cf47362 100755 --- a/Libraries/Pickers/AbstractActionSheetPicker.m +++ b/Libraries/Pickers/AbstractActionSheetPicker.m @@ -30,8 +30,7 @@ #import #import -CG_INLINE BOOL isIPhone4() -{ +CG_INLINE BOOL isIPhone4() { struct utsname systemInfo; uname(&systemInfo); @@ -49,8 +48,43 @@ CG_INLINE BOOL isIPhone4() #define OrientationMaskSupportsOrientation(mask, orientation) ((mask & (1 << orientation)) != 0) +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 -@interface AbstractActionSheetPicker () +@interface MyPopoverController : UIPopoverController +@end + +@implementation MyPopoverController ++ (BOOL)canShowPopover { + if (IS_IPAD) { + if ([UITraitCollection class]) { + UITraitCollection *traits = [UIApplication sharedApplication].keyWindow.traitCollection; + if (traits.horizontalSizeClass == UIUserInterfaceSizeClassCompact) + return NO; + } + return YES; + } + return NO; +} + +- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection { + return UIModalPresentationNone; +} +@end + +#else + +@interface MyPopoverController:UIPopoverController +@end + +@implementation MyPopoverController ++(BOOL)canShowPopover { + return IS_IPAD; +} +@end + +#endif + +@interface AbstractActionSheetPicker () @property(nonatomic, strong) UIBarButtonItem *barButtonItem; @property(nonatomic, strong) UIBarButtonItem *doneBarButtonItem; @@ -59,8 +93,9 @@ @interface AbstractActionSheetPicker () @property(nonatomic, unsafe_unretained) id target; @property(nonatomic, assign) SEL successAction; @property(nonatomic, assign) SEL cancelAction; -@property(nonatomic, strong) SWActionSheet *actionSheet; @property(nonatomic, strong) UIPopoverController *popOverController; +@property(nonatomic, strong) CIFilter *filter; +@property(nonatomic, strong) CIContext *context; @property(nonatomic, strong) NSObject *selfReference; - (void)presentPickerForView:(UIView *)aView; @@ -94,22 +129,25 @@ @implementation AbstractActionSheetPicker #pragma mark - Abstract Implementation -- (id)initWithTarget:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin -{ +- (instancetype)init { self = [super init]; - if ( self ) - { - self.target = target; - self.successAction = successAction; - self.cancelAction = cancelActionOrNil; + if (self) { self.presentFromRect = CGRectZero; + self.popoverBackgroundViewClass = nil; + self.popoverDisabled = NO; - if ( [origin isKindOfClass:[UIBarButtonItem class]] ) - self.barButtonItem = origin; - else if ( [origin isKindOfClass:[UIView class]] ) - self.containerView = origin; - else - NSAssert(NO, @"Invalid origin provided to ActionSheetPicker ( %@ )", origin); +#pragma clang diagnostic push +#pragma ide diagnostic ignored "UnavailableInDeploymentTarget" + if ([UIApplication instancesRespondToSelector:@selector(supportedInterfaceOrientationsForWindow:)]) + self.supportedInterfaceOrientations = (UIInterfaceOrientationMask) [[UIApplication sharedApplication] + supportedInterfaceOrientationsForWindow: + [UIApplication sharedApplication].keyWindow]; + else { + self.supportedInterfaceOrientations = UIInterfaceOrientationMaskAllButUpsideDown; + if (IS_IPAD) + self.supportedInterfaceOrientations |= (1 << UIInterfaceOrientationPortraitUpsideDown); + } +#pragma clang diagnostic pop UIBarButtonItem *sysDoneButton = [self createButtonWithType:UIBarButtonSystemItemDone target:self action:@selector(actionPickerDone:)]; @@ -120,44 +158,74 @@ - (id)initWithTarget:(id)target successAction:(SEL)successAction cancelAction:(S [self setCancelBarButtonItem:sysCancelButton]; [self setDoneBarButtonItem:sysDoneButton]; + self.tapDismissAction = TapActionNone; //allows us to use this without needing to store a reference in calling class self.selfReference = self; + + NSMutableParagraphStyle *labelParagraphStyle = [[NSMutableParagraphStyle alloc] init]; + labelParagraphStyle.alignment = NSTextAlignmentCenter; + self.pickerTextAttributes = [@{NSParagraphStyleAttributeName : labelParagraphStyle} mutableCopy]; + + self.context = [CIContext contextWithOptions:nil]; + self.filter = [CIFilter filterWithName:@"CIGaussianBlur"]; } + return self; } -- (void)dealloc -{ + +- (void)setTextColor:(UIColor *)textColor { + if (self.pickerTextAttributes) { + self.pickerTextAttributes[NSForegroundColorAttributeName] = textColor; + } else { + self.pickerTextAttributes = [@{NSForegroundColorAttributeName : [UIColor whiteColor]} mutableCopy]; + } +} + +- (instancetype)initWithTarget:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin { + self = [self init]; + if (self) { + self.target = target; + self.successAction = successAction; + self.cancelAction = cancelActionOrNil; + + if ([origin isKindOfClass:[UIBarButtonItem class]]) + self.barButtonItem = origin; + else if ([origin isKindOfClass:[UIView class]]) + self.containerView = origin; + else + NSAssert(NO, @"Invalid origin provided to ActionSheetPicker ( %@ )", origin); + } + return self; +} + +- (void)dealloc { //need to clear picker delegates and datasources, otherwise they may call this object after it's gone - if ( [self.pickerView respondsToSelector:@selector(setDelegate:)] ) + if ([self.pickerView respondsToSelector:@selector(setDelegate:)]) [self.pickerView performSelector:@selector(setDelegate:) withObject:nil]; - if ( [self.pickerView respondsToSelector:@selector(setDataSource:)] ) + if ([self.pickerView respondsToSelector:@selector(setDataSource:)]) [self.pickerView performSelector:@selector(setDataSource:) withObject:nil]; - if ( [self.pickerView respondsToSelector:@selector(removeTarget:action:forControlEvents:)] ) - [((UIControl*)self.pickerView) removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents]; + if ([self.pickerView respondsToSelector:@selector(removeTarget:action:forControlEvents:)]) + [((UIControl *) self.pickerView) removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents]; self.target = nil; [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (UIView *)configuredPickerView -{ +- (UIView *)configuredPickerView { NSAssert(NO, @"This is an abstract class, you must use a subclass of AbstractActionSheetPicker (like ActionSheetStringPicker)"); return nil; } -- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin -{ +- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin { NSAssert(NO, @"This is an abstract class, you must use a subclass of AbstractActionSheetPicker (like ActionSheetStringPicker)"); } -- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin -{ - if ( target && cancelAction && [target respondsToSelector:cancelAction] ) - { +- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin { + if (target && cancelAction && [target respondsToSelector:cancelAction]) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" [target performSelector:cancelAction withObject:origin]; @@ -167,25 +235,22 @@ - (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id #pragma mark - Actions -- (void)showActionSheetPicker -{ +- (void)showActionSheetPicker { UIView *masterView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.viewSize.width, 260)]; // to fix bug, appeared only on iPhone 4 Device: https://github.com/skywinder/ActionSheetPicker-3.0/issues/5 - if ( isIPhone4() ) - { + if (isIPhone4()) { masterView.backgroundColor = [UIColor colorWithRed:0.97 green:0.97 blue:0.97 alpha:1.0]; } self.toolbar = [self createPickerToolbarWithTitle:self.title]; [masterView addSubview:self.toolbar]; //ios7 picker draws a darkened alpha-only region on the first and last 8 pixels horizontally, but blurs the rest of its background. To make the whole popup appear to be edge-to-edge, we have to add blurring to the remaining left and right edges. - if ( NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1 ) - { - CGRect f = CGRectMake(0, self.toolbar.frame.origin.y, 8, masterView.frame.size.height - self.toolbar.frame.origin.y); - UIToolbar *leftEdge = [[UIToolbar alloc] initWithFrame:f]; - f.origin.x = masterView.frame.size.width - 8; - UIToolbar *rightEdge = [[UIToolbar alloc] initWithFrame:f]; + if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { + CGRect rect = CGRectMake(0, self.toolbar.frame.origin.y, _borderWidth, masterView.frame.size.height - self.toolbar.frame.origin.y); + UIToolbar *leftEdge = [[UIToolbar alloc] initWithFrame:rect]; + rect.origin.x = masterView.frame.size.width - _borderWidth; + UIToolbar *rightEdge = [[UIToolbar alloc] initWithFrame:rect]; #pragma clang diagnostic push #pragma ide diagnostic ignored "UnavailableInDeploymentTarget" leftEdge.barTintColor = rightEdge.barTintColor = self.toolbar.barTintColor; @@ -196,31 +261,66 @@ - (void)showActionSheetPicker self.pickerView = [self configuredPickerView]; NSAssert(_pickerView != NULL, @"Picker view failed to instantiate, perhaps you have invalid component data."); + // toolbar hidden remove the toolbar frame and update pickerview frame + if (self.toolbar.hidden) { + int halfWidth = (int) (_borderWidth * 0.5f); + masterView.frame = CGRectMake(0, 0, self.viewSize.width, 220); + self.pickerView.frame = CGRectMake(0, halfWidth, self.viewSize.width, 220 - halfWidth); + } [masterView addSubview:_pickerView]; - [self presentPickerForView:masterView]; + + if ((![MyPopoverController canShowPopover] || self.popoverDisabled) && !self.pickerBackgroundColor && !self.toolbarBackgroundColor && [self.pickerBlurRadius intValue] > 0) { + [self blurPickerBackground]; + } else { + [self presentPickerForView:masterView]; + } + +#pragma clang diagnostic push +#pragma ide diagnostic ignored "UnavailableInDeploymentTarget" + { + switch (self.tapDismissAction) { + case TapActionNone: + break; + case TapActionSuccess: { + // add tap dismiss action + self.actionSheet.window.userInteractionEnabled = YES; + UITapGestureRecognizer *tapAction = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(actionPickerDone:)]; + tapAction.delegate = self; + [self.actionSheet.window addGestureRecognizer:tapAction]; + break; + } + case TapActionCancel: { + // add tap dismiss action + self.actionSheet.window.userInteractionEnabled = YES; + UITapGestureRecognizer *tapAction = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(actionPickerCancel:)]; + tapAction.delegate = self; + [self.actionSheet.window addGestureRecognizer:tapAction]; + break; + } + }; + } +#pragma clang diagnostic pop + } -- (IBAction)actionPickerDone:(id)sender -{ +- (IBAction)actionPickerDone:(id)sender { [self notifyTarget:self.target didSucceedWithAction:self.successAction origin:[self storedOrigin]]; [self dismissPicker]; } -- (IBAction)actionPickerCancel:(id)sender -{ +- (IBAction)actionPickerCancel:(id)sender { [self notifyTarget:self.target didCancelWithAction:self.cancelAction origin:[self storedOrigin]]; [self dismissPicker]; } -- (void)dismissPicker -{ +- (void)dismissPicker { #if __IPHONE_4_1 <= __IPHONE_OS_VERSION_MAX_ALLOWED - if ( self.actionSheet ) + if (self.actionSheet) #else - if (self.actionSheet && [self.actionSheet isVisible]) + if (self.actionSheet && [self.actionSheet isVisible]) #endif [_actionSheet dismissWithClickedButtonIndex:0 animated:YES]; - else if ( self.popOverController && self.popOverController.popoverVisible ) + else if (self.popOverController && self.popOverController.popoverVisible) [_popOverController dismissPopoverAnimated:YES]; self.actionSheet = nil; self.popOverController = nil; @@ -229,51 +329,117 @@ - (void)dismissPicker #pragma mark - Custom Buttons -- (void)addCustomButtonWithTitle:(NSString *)title value:(id)value -{ - if ( !self.customButtons ) +- (NSMutableArray *)customButtons { + if (!_customButtons) { _customButtons = [[NSMutableArray alloc] init]; - if ( !title ) + } + + return _customButtons; +} + +- (void)addCustomButtonWithTitle:(NSString *)title value:(id)value { + if (!title) title = @""; - if ( !value ) + if (!value) value = @0; NSDictionary *buttonDetails = @{ kButtonTitle : title, + kActionType : @(ActionTypeValue), kButtonValue : value }; [self.customButtons addObject:buttonDetails]; } -- (IBAction)customButtonPressed:(id)sender -{ +- (void)addCustomButtonWithTitle:(NSString *)title actionBlock:(ActionBlock)block { + if (!title) + title = @""; + if (!block) + block = (^{ + }); + NSDictionary *buttonDetails = @{ + kButtonTitle : title, + kActionType : @(ActionTypeBlock), + kButtonValue : [block copy] + }; + [self.customButtons addObject:buttonDetails]; +} + +- (void)addCustomButtonWithTitle:(NSString *)title target:(id)target selector:(SEL)selector { + if (!title) + title = @""; + if (!target) + target = [NSNull null]; + NSDictionary *buttonDetails = @{ + kButtonTitle : title, + kActionType : @(ActionTypeSelector), + kActionTarget : target, + kButtonValue : [NSValue valueWithPointer:selector] + }; + [self.customButtons addObject:buttonDetails]; +} + +- (IBAction)customButtonPressed:(id)sender { UIBarButtonItem *button = (UIBarButtonItem *) sender; NSInteger index = button.tag; - NSAssert((index >= 0 && index < self.customButtons.count), @"Bad custom button tag: %ld, custom button count: %lu", (long)index, (unsigned long)self.customButtons.count); - NSAssert([self.pickerView respondsToSelector:@ - selector(selectRow:inComponent:animated:)], @"customButtonPressed not overridden, cannot interact with subclassed pickerView"); + NSAssert((index >= 0 && index < self.customButtons.count), @"Bad custom button tag: %ld, custom button count: %lu", (long) index, (unsigned long) self.customButtons.count); + NSDictionary *buttonDetails = (self.customButtons)[(NSUInteger) index]; NSAssert(buttonDetails != NULL, @"Custom button dictionary is invalid"); - NSInteger buttonValue = [buttonDetails[kButtonValue] intValue]; - UIPickerView *picker = (UIPickerView *) self.pickerView; - NSAssert(picker != NULL, @"PickerView is invalid"); - [picker selectRow:buttonValue inComponent:0 animated:YES]; - if ( [self respondsToSelector:@selector(pickerView:didSelectRow:inComponent:)] ) - { - void (*objc_msgSendTyped)(id target, SEL _cmd, id pickerView, NSInteger row, NSInteger component) = (void *) objc_msgSend; // sending Integers as params - objc_msgSendTyped(self, @selector(pickerView:didSelectRow:inComponent:), picker, buttonValue, 0); + + ActionType actionType = (ActionType) [buttonDetails[kActionType] integerValue]; + switch (actionType) { + case ActionTypeValue: { + NSAssert([self.pickerView respondsToSelector:@ + selector(selectRow:inComponent:animated:)], @"customButtonPressed not overridden, cannot interact with subclassed pickerView"); + NSInteger buttonValue = [buttonDetails[kButtonValue] integerValue]; + UIPickerView *picker = (UIPickerView *) self.pickerView; + NSAssert(picker != NULL, @"PickerView is invalid"); + [picker selectRow:buttonValue inComponent:0 animated:YES]; + if ([self respondsToSelector:@selector(pickerView:didSelectRow:inComponent:)]) { + void (*objc_msgSendTyped)(id target, SEL _cmd, id pickerView, NSInteger row, NSInteger component) = (void *) objc_msgSend; // sending Integers as params + objc_msgSendTyped(self, @selector(pickerView:didSelectRow:inComponent:), picker, buttonValue, 0); + } + break; + } + + case ActionTypeBlock: { + ActionBlock actionBlock = buttonDetails[kButtonValue]; + [self dismissPicker]; + if (actionBlock) + actionBlock(); + break; + } + + case ActionTypeSelector: { + SEL selector = [buttonDetails[kButtonValue] pointerValue]; + id target = buttonDetails[kActionTarget]; + [self dismissPicker]; + if (target && [target respondsToSelector:selector]) { + SuppressPerformSelectorLeakWarning ( + [target performSelector:selector]; + ); + } + break; + } + + default: + NSAssert(false, @"Unknown action type"); + break; } } // Allow the user to specify a custom cancel button -- (void)setCancelButton:(UIBarButtonItem *)button -{ - if ( [button.customView isKindOfClass:[UIButton class]] ) - { +- (void)setCancelButton:(UIBarButtonItem *)button { + if (!button) { + self.hideCancel = YES; + return; + } + + if ([button.customView isKindOfClass:[UIButton class]]) { UIButton *uiButton = (UIButton *) button.customView; [uiButton addTarget:self action:@selector(actionPickerCancel:) forControlEvents:UIControlEventTouchUpInside]; } - else - { + else { [button setTarget:self]; [button setAction:@selector(actionPickerCancel:)]; } @@ -281,16 +447,13 @@ - (void)setCancelButton:(UIBarButtonItem *)button } // Allow the user to specify a custom done button -- (void)setDoneButton:(UIBarButtonItem *)button -{ - if ( [button.customView isKindOfClass:[UIButton class]] ) - { +- (void)setDoneButton:(UIBarButtonItem *)button { + if ([button.customView isKindOfClass:[UIButton class]]) { UIButton *uiButton = (UIButton *) button.customView; [button setAction:@selector(actionPickerDone:)]; [uiButton addTarget:self action:@selector(actionPickerDone:) forControlEvents:UIControlEventTouchUpInside]; } - else - { + else { [button setTarget:self]; [button setAction:@selector(actionPickerDone:)]; } @@ -299,38 +462,35 @@ - (void)setDoneButton:(UIBarButtonItem *)button self.doneBarButtonItem = button; } -- (void)hidePickerWithCancelAction -{ +- (void)hidePickerWithCancelAction { [self actionPickerCancel:nil]; } -- (UIToolbar *)createPickerToolbarWithTitle:(NSString *)title -{ +- (UIToolbar *)createPickerToolbarWithTitle:(NSString *)title { CGRect frame = CGRectMake(0, 0, self.viewSize.width, 44); UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:frame]; pickerToolbar.barStyle = (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) ? UIBarStyleDefault : UIBarStyleBlackTranslucent; + pickerToolbar.barTintColor = self.toolbarBackgroundColor; + pickerToolbar.tintColor = self.toolbarButtonsColor; + NSMutableArray *barItems = [[NSMutableArray alloc] init]; - if ( !self.hideCancel ) - { + if (!self.hideCancel) { [barItems addObject:self.cancelBarButtonItem]; } NSInteger index = 0; - for (NSDictionary *buttonDetails in self.customButtons) - { + for (NSDictionary *buttonDetails in self.customButtons) { NSString *buttonTitle = buttonDetails[kButtonTitle]; UIBarButtonItem *button; - if ( NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1 ) - { + if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { button = [[UIBarButtonItem alloc] initWithTitle:buttonTitle style:UIBarButtonItemStylePlain target:self action:@selector(customButtonPressed:)]; } - else - { + else { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" button = [[UIBarButtonItem alloc] initWithTitle:buttonTitle style:UIBarButtonItemStyleBordered @@ -345,8 +505,7 @@ - (UIToolbar *)createPickerToolbarWithTitle:(NSString *)title UIBarButtonItem *flexSpace = [self createButtonWithType:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; [barItems addObject:flexSpace]; - if ( title ) - { + if (title) { UIBarButtonItem *labelButton; labelButton = [self createToolbarLabelWithTitle:title titleTextAttributes:self.titleTextAttributes andAttributedTitle:self.attributedTitle]; @@ -362,8 +521,7 @@ - (UIToolbar *)createPickerToolbarWithTitle:(NSString *)title - (UIBarButtonItem *)createToolbarLabelWithTitle:(NSString *)aTitle titleTextAttributes:(NSDictionary *)titleTextAttributes - andAttributedTitle:(NSAttributedString *)attributedTitle -{ + andAttributedTitle:(NSAttributedString *)attributedTitle { UILabel *toolBarItemLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 180, 30)]; [toolBarItemLabel setTextAlignment:NSTextAlignmentCenter]; [toolBarItemLabel setBackgroundColor:[UIColor clearColor]]; @@ -379,20 +537,17 @@ - (UIBarButtonItem *)createToolbarLabelWithTitle:(NSString *)aTitle toolBarItemLabel.attributedText = attributedTitle; textSize = toolBarItemLabel.attributedText.size; } - else - { + else { [toolBarItemLabel setTextColor:(NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) ? [UIColor blackColor] : [UIColor whiteColor]]; [toolBarItemLabel setFont:[UIFont boldSystemFontOfSize:16]]; toolBarItemLabel.text = aTitle; - if ( NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1 ) - { + if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_6_1) { #pragma clang diagnostic push #pragma ide diagnostic ignored "UnavailableInDeploymentTarget" textSize = [[toolBarItemLabel text] sizeWithAttributes:@{NSFontAttributeName : [toolBarItemLabel font]}]; #pragma clang diagnostic pop - } else - { + } else { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" textSize = [[toolBarItemLabel text] sizeWithFont:[toolBarItemLabel font]]; @@ -402,8 +557,7 @@ - (UIBarButtonItem *)createToolbarLabelWithTitle:(NSString *)aTitle strikeWidth = textSize.width; - if ( strikeWidth < 180 ) - { + if (strikeWidth < 180) { [toolBarItemLabel sizeToFit]; } @@ -411,79 +565,123 @@ - (UIBarButtonItem *)createToolbarLabelWithTitle:(NSString *)aTitle return buttonLabel; } -- (UIBarButtonItem *)createButtonWithType:(UIBarButtonSystemItem)type target:(id)target action:(SEL)buttonAction -{ +- (UIBarButtonItem *)createButtonWithType:(UIBarButtonSystemItem)type target:(id)target action:(SEL)buttonAction { UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:type target:target action:buttonAction]; return barButton; } +#pragma mark - Custom Color + +- (void)setPickerBackgroundColor:(UIColor *)backgroundColor { + _pickerBackgroundColor = backgroundColor; + _actionSheet.bgView.backgroundColor = backgroundColor; +} + +#pragma mark - Picker blur effect + +- (void)blurPickerBackground { + UIWindow *window = [UIApplication sharedApplication].delegate.window; + UIViewController *rootViewController = window.rootViewController; + + UIView *masterView = self.pickerView.superview; + + self.pickerView.backgroundColor = [UIColor clearColor]; + masterView.backgroundColor = [UIColor clearColor]; + + // Get the snapshot + UIGraphicsBeginImageContext(rootViewController.view.bounds.size); + [rootViewController.view drawViewHierarchyInRect:rootViewController.view.bounds afterScreenUpdates:NO]; + UIImage *backgroundImage = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + [self presentPickerForView:masterView]; + + // Crop the snapshot to match picker frame + CIImage *image = [CIImage imageWithCGImage:[backgroundImage CGImage]]; + [self.filter setValue:image forKey:kCIInputImageKey]; + [self.filter setValue:self.pickerBlurRadius forKey:kCIInputRadiusKey]; + + CGRect blurFrame = [rootViewController.view convertRect:self.pickerView.frame fromView:masterView]; + // CoreImage coordinate system and UIKit coordinate system differs, so we need to adjust the frame + blurFrame.origin.y = - (blurFrame.origin.y - rootViewController.view.frame.size.height) - blurFrame.size.height; + + CGImageRef imageRef = [self.context createCGImage:self.filter.outputImage fromRect:blurFrame]; + + UIImageView *blurredImageView = [[UIImageView alloc] initWithFrame:self.pickerView.frame]; + blurredImageView.image = [UIImage imageWithCGImage:imageRef]; + blurredImageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + + [masterView addSubview:blurredImageView]; + [masterView sendSubviewToBack:blurredImageView]; + + CGImageRelease(imageRef); +} + #pragma mark - Utilities and Accessors -- (CGSize)viewSize -{ - if ( IS_IPAD ) - { - return CGSizeMake(320, 320); +- (CGSize)viewSize { + if (IS_IPAD) { + if (!self.popoverDisabled && [MyPopoverController canShowPopover]) + return CGSizeMake(320, 320); + return [UIApplication sharedApplication].keyWindow.bounds.size; } - #if defined(__IPHONE_8_0) +#if defined(__IPHONE_8_0) if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_7_1) { //iOS 7.1 or earlier - if ( [self isViewPortrait] ) - return CGSizeMake(320 , IS_WIDESCREEN ? 568 : 480); + if ([self isViewPortrait]) + return CGSizeMake(320, IS_WIDESCREEN ? 568 : 480); return CGSizeMake(IS_WIDESCREEN ? 568 : 480, 320); - }else{ + } else { //iOS 8 or later return [[UIScreen mainScreen] bounds].size; } - #else - if ( [self isViewPortrait] ) - return CGSizeMake(320 , IS_WIDESCREEN ? 568 : 480); - return CGSizeMake(IS_WIDESCREEN ? 568 : 480, 320); - #endif +#else + if ( [self isViewPortrait] ) + return CGSizeMake(320 , IS_WIDESCREEN ? 568 : 480); + return CGSizeMake(IS_WIDESCREEN ? 568 : 480, 320); +#endif } -- (BOOL)isViewPortrait -{ +- (BOOL)isViewPortrait { return UIInterfaceOrientationIsPortrait([UIApplication sharedApplication].statusBarOrientation); } -- (BOOL)isValidOrigin:(id)origin -{ - if ( !origin ) +- (BOOL)isValidOrigin:(id)origin { + if (!origin) return NO; BOOL isButton = [origin isKindOfClass:[UIBarButtonItem class]]; BOOL isView = [origin isKindOfClass:[UIView class]]; return (isButton || isView); } -- (id)storedOrigin -{ - if ( self.barButtonItem ) +- (id)storedOrigin { + if (self.barButtonItem) return self.barButtonItem; return self.containerView; } #pragma mark - Popovers and ActionSheets -- (void)presentPickerForView:(UIView *)aView -{ +- (void)presentPickerForView:(UIView *)aView { self.presentFromRect = aView.frame; - if ( IS_IPAD ) + if (!self.popoverDisabled && [MyPopoverController canShowPopover]) [self configureAndPresentPopoverForView:aView]; else [self configureAndPresentActionSheetForView:aView]; } -- (void)configureAndPresentActionSheetForView:(UIView *)aView -{ +- (void)configureAndPresentActionSheetForView:(UIView *)aView { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil]; _actionSheet = [[SWActionSheet alloc] initWithView:aView]; + if (self.pickerBackgroundColor) { + _actionSheet.bgView.backgroundColor = self.pickerBackgroundColor; + } [self presentActionSheet:_actionSheet]; @@ -493,27 +691,20 @@ - (void)configureAndPresentActionSheetForView:(UIView *)aView [UIView commitAnimations]; } -- (void) didRotate:(NSNotification *)notification -{ - UIInterfaceOrientationMask supportedInterfaceOrientations = (UIInterfaceOrientationMask) [[UIApplication sharedApplication] - supportedInterfaceOrientationsForWindow: - [UIApplication sharedApplication].keyWindow]; - - if (OrientationMaskSupportsOrientation(supportedInterfaceOrientations, DEVICE_ORIENTATION)) +- (void)didRotate:(NSNotification *)notification { + if (OrientationMaskSupportsOrientation(self.supportedInterfaceOrientations, DEVICE_ORIENTATION)) [self dismissPicker]; } -- (void)presentActionSheet:(SWActionSheet *)actionSheet -{ +- (void)presentActionSheet:(SWActionSheet *)actionSheet { NSParameterAssert(actionSheet != NULL); - if ( self.barButtonItem ) + if (self.barButtonItem) [actionSheet showFromBarButtonItem:_barButtonItem animated:YES]; else [actionSheet showInContainerView]; } -- (void)configureAndPresentPopoverForView:(UIView *)aView -{ +- (void)configureAndPresentPopoverForView:(UIView *)aView { UIViewController *viewController = [[UIViewController alloc] initWithNibName:nil bundle:nil]; viewController.view = aView; @@ -523,59 +714,89 @@ - (void)configureAndPresentPopoverForView:(UIView *)aView viewController.preferredContentSize = aView.frame.size; #pragma clang diagnostic pop } - else - { + else { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" viewController.contentSizeForViewInPopover = viewController.view.frame.size; #pragma clang diagnostic pop } - _popOverController = [[UIPopoverController alloc] initWithContentViewController:viewController]; + _popOverController = [[MyPopoverController alloc] initWithContentViewController:viewController]; _popOverController.delegate = self; + if (self.pickerBackgroundColor) { + self.popOverController.backgroundColor = self.pickerBackgroundColor; + } + if (self.popoverBackgroundViewClass) { + [self.popOverController setPopoverBackgroundViewClass:self.popoverBackgroundViewClass]; + } + [self presentPopover:_popOverController]; } -- (void)presentPopover:(UIPopoverController *)popover -{ +- (void)presentPopover:(UIPopoverController *)popover { NSParameterAssert(popover != NULL); - if ( self.barButtonItem ) - { - [popover presentPopoverFromBarButtonItem:_barButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny - animated:YES]; + if (self.barButtonItem) { + if (_containerView != nil) { + [popover presentPopoverFromRect:CGRectMake(_containerView.frame.size.width / 2.f, 0.f, 0, 0) inView:_containerView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; + } else { + [popover presentPopoverFromBarButtonItem:_barButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; + } + return; } - else if ( (self.containerView) ) - { - [popover presentPopoverFromRect:_containerView.bounds inView:_containerView - permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; + else if ((self.containerView)) { + dispatch_async(dispatch_get_main_queue(), ^{ + [popover presentPopoverFromRect:_containerView.bounds inView:_containerView + permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; + + }); return; } // Unfortunately, things go to hell whenever you try to present a popover from a table view cell. These are failsafes. UIView *origin = nil; CGRect presentRect = CGRectZero; - @try - { + @try { origin = (_containerView.superview ? _containerView.superview : _containerView); presentRect = origin.bounds; - [popover presentPopoverFromRect:presentRect inView:origin permittedArrowDirections:UIPopoverArrowDirectionAny - animated:YES]; + dispatch_async(dispatch_get_main_queue(), ^{ + [popover presentPopoverFromRect:presentRect inView:origin + permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; + + }); } - @catch (NSException *exception) - { + @catch (NSException *exception) { origin = [[[[UIApplication sharedApplication] keyWindow] rootViewController] view]; presentRect = CGRectMake(origin.center.x, origin.center.y, 1, 1); - [popover presentPopoverFromRect:presentRect inView:origin permittedArrowDirections:UIPopoverArrowDirectionAny - animated:YES]; + dispatch_async(dispatch_get_main_queue(), ^{ + [popover presentPopoverFromRect:presentRect inView:origin + permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; + + }); } } #pragma mark - Popoverdelegate -- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController -{ - [self notifyTarget:self.target didCancelWithAction:self.cancelAction origin:[self storedOrigin]]; + +- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController { + switch (self.tapDismissAction) { + case TapActionSuccess: { + [self notifyTarget:self.target didSucceedWithAction:self.successAction origin:self.storedOrigin]; + break; + } + case TapActionNone: + case TapActionCancel: { + [self notifyTarget:self.target didCancelWithAction:self.cancelAction origin:self.storedOrigin]; + break; + } + }; } +#pragma mark UIGestureRecognizerDelegate + +- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { + CGPoint location = [gestureRecognizer locationInView:self.toolbar]; + return !CGRectContainsPoint(self.toolbar.bounds, location); +} @end diff --git a/Libraries/Pickers/ActionSheetCustomPicker.h b/Libraries/Pickers/ActionSheetCustomPicker.h index 8d9b6df..9b177f3 100644 --- a/Libraries/Pickers/ActionSheetCustomPicker.h +++ b/Libraries/Pickers/ActionSheetCustomPicker.h @@ -24,14 +24,14 @@ ///////////////////////////////////////////////////////////////////////// /** Designated init */ -- (id)initWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin; +- (instancetype)initWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin; -- (id)initWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections; +- (instancetype)initWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections; /** Convenience class method for creating an launched */ -+ (id)showPickerWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin; ++ (instancetype)showPickerWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin; -+ (id)showPickerWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections; ++ (instancetype)showPickerWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections; @end diff --git a/Libraries/Pickers/ActionSheetCustomPicker.m b/Libraries/Pickers/ActionSheetCustomPicker.m index e0ab860..6b7734a 100644 --- a/Libraries/Pickers/ActionSheetCustomPicker.m +++ b/Libraries/Pickers/ActionSheetCustomPicker.m @@ -18,20 +18,20 @@ @implementation ActionSheetCustomPicker #pragma mark - Init ///////////////////////////////////////////////////////////////////////// -- (id)initWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin +- (instancetype)initWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin { return [self initWithTitle:title delegate:delegate showCancelButton:showCancelButton origin:origin initialSelections:nil]; } -+ (id)showPickerWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin ++ (instancetype)showPickerWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin { return [self showPickerWithTitle:title delegate:delegate showCancelButton:showCancelButton origin:origin initialSelections:nil ]; } -- (id)initWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections +- (instancetype)initWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections { if ( self = [self initWithTarget:nil successAction:nil cancelAction:nil origin:origin] ) { @@ -48,7 +48,7 @@ - (id)initWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections ++ (instancetype)showPickerWithTitle:(NSString *)title delegate:(id )delegate showCancelButton:(BOOL)showCancelButton origin:(id)origin initialSelections:(NSArray *)initialSelections { ActionSheetCustomPicker *picker = [[ActionSheetCustomPicker alloc] initWithTitle:title delegate:delegate showCancelButton:showCancelButton origin:origin @@ -65,6 +65,7 @@ - (UIView *)configuredPickerView { CGRect pickerFrame = CGRectMake(0, 40, self.viewSize.width, 216); UIPickerView *pv = [[UIPickerView alloc] initWithFrame:pickerFrame]; + self.pickerView = pv; // Default to our delegate being the picker's delegate and datasource pv.delegate = _delegate; @@ -80,6 +81,10 @@ - (UIView *)configuredPickerView NSInteger row = [(NSNumber *) self.initialSelections[i] integerValue]; NSAssert([pv numberOfRowsInComponent:i] > row, @"Number of sections not match"); [pv selectRow:row inComponent:i animated:NO]; + + // Strangely, the above selectRow:inComponent:animated: will not call + // pickerView:didSelectRow:inComponent: automatically, so we manually call it. + [pv reloadAllComponents]; } } @@ -90,7 +95,6 @@ - (UIView *)configuredPickerView { [_delegate actionSheetPicker:self configurePickerView:pv]; } - self.pickerView = pv; return pv; } diff --git a/Libraries/Pickers/ActionSheetDatePicker.h b/Libraries/Pickers/ActionSheetDatePicker.h index 58619fa..d64a69a 100755 --- a/Libraries/Pickers/ActionSheetDatePicker.h +++ b/Libraries/Pickers/ActionSheetDatePicker.h @@ -29,30 +29,59 @@ @class ActionSheetDatePicker; -typedef void(^ActionDateDoneBlock)(ActionSheetDatePicker *picker, NSDate *selectedDate, id origin); +typedef void(^ActionDateDoneBlock)(ActionSheetDatePicker *picker, id selectedDate, id origin); //selectedDate is NSDate or NSNumber for "UIDatePickerModeCountDownTimer" typedef void(^ActionDateCancelBlock)(ActionSheetDatePicker *picker); @interface ActionSheetDatePicker : AbstractActionSheetPicker -@property (nonatomic) NSDate *minimumDate; -@property (nonatomic) NSDate *maximumDate; -@property (nonatomic) NSInteger minuteInterval; -@property (nonatomic) NSCalendar *calendar; -@property (nonatomic) NSTimeZone *timeZone; -@property (nonatomic) NSLocale *locale; +@property (nonatomic, retain) NSDate *minimumDate; // specify min/max date range. default is nil. When min > max, the values are ignored. Ignored in countdown timer mode +@property (nonatomic, retain) NSDate *maximumDate; // default is nil -+ (id)showPickerWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin; +@property (nonatomic) NSInteger minuteInterval; // display minutes wheel with interval. interval must be evenly divided into 60. default is 1. min is 1, max is 30 -+ (id)showPickerWithTitle:(NSString *)title +@property (nonatomic, retain) NSLocale *locale; // default is [NSLocale currentLocale]. setting nil returns to default +@property (nonatomic, copy) NSCalendar *calendar; // default is [NSCalendar currentCalendar]. setting nil returns to default +@property (nonatomic, retain) NSTimeZone *timeZone; // default is nil. use current time zone or time zone from calendar + +@property (nonatomic, assign) NSTimeInterval countDownDuration; // for UIDatePickerModeCountDownTimer, ignored otherwise. default is 0.0. limit is 23:59 (86,399 seconds). value being set is div 60 (drops remaining seconds). + +@property (nonatomic, copy) ActionDateDoneBlock onActionSheetDone; +@property (nonatomic, copy) ActionDateCancelBlock onActionSheetCancel; + ++ (instancetype)showPickerWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin; + ++ (instancetype)showPickerWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction; + ++ (instancetype)showPickerWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate + minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate + target:(id)target action:(SEL)action origin:(id)origin; + ++ (instancetype)showPickerWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate doneBlock:(ActionDateDoneBlock)doneBlock cancelBlock:(ActionDateCancelBlock)cancelBlock origin:(UIView*)view; ++ (instancetype)showPickerWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode + selectedDate:(NSDate *)selectedDate + minimumDate:(NSDate *)minimumDate + maximumDate:(NSDate *)maximumDate + doneBlock:(ActionDateDoneBlock)doneBlock + cancelBlock:(ActionDateCancelBlock)cancelBlock + origin:(UIView*)view; + + - (id)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin; -- (id)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction; +- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate target:(id)target action:(SEL)action origin:(id)origin; + +- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction; + +- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate target:(id)target action:(SEL)action cancelAction:(SEL)cancelAction origin:(id)origin; + - (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode @@ -63,7 +92,4 @@ typedef void(^ActionDateCancelBlock)(ActionSheetDatePicker *picker); - (void)eventForDatePicker:(id)sender; -@property (nonatomic, copy) ActionDateDoneBlock onActionSheetDone; -@property (nonatomic, copy) ActionDateCancelBlock onActionSheetCancel; - @end diff --git a/Libraries/Pickers/ActionSheetDatePicker.m b/Libraries/Pickers/ActionSheetDatePicker.m index 51bdc5c..fd5df63 100755 --- a/Libraries/Pickers/ActionSheetDatePicker.m +++ b/Libraries/Pickers/ActionSheetDatePicker.m @@ -32,15 +32,11 @@ @interface ActionSheetDatePicker() @property (nonatomic, assign) UIDatePickerMode datePickerMode; @property (nonatomic, strong) NSDate *selectedDate; -@property (nonatomic, assign) NSTimeInterval duration; @end @implementation ActionSheetDatePicker -@synthesize selectedDate = _selectedDate; -@synthesize datePickerMode = _datePickerMode; -@synthesize duration = _duration; -+ (id)showPickerWithTitle:(NSString *)title ++ (instancetype)showPickerWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin { ActionSheetDatePicker *picker = [[ActionSheetDatePicker alloc] initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:target action:action origin:origin]; @@ -48,7 +44,26 @@ + (id)showPickerWithTitle:(NSString *)title return picker; } -+ (id)showPickerWithTitle:(NSString *)title ++ (instancetype)showPickerWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate + target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction { + ActionSheetDatePicker *picker = [[ActionSheetDatePicker alloc] initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:target action:action origin:origin cancelAction:cancelAction]; + [picker showActionSheetPicker]; + return picker; +} + ++ (instancetype)showPickerWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate + minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate + target:(id)target action:(SEL)action origin:(id)origin { + ActionSheetDatePicker *picker = [[ActionSheetDatePicker alloc] initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:target action:action origin:origin]; + [picker setMinimumDate:minimumDate]; + [picker setMaximumDate:maximumDate]; + [picker showActionSheetPicker]; + return picker; +} + ++ (instancetype)showPickerWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate doneBlock:(ActionDateDoneBlock)doneBlock @@ -65,6 +80,26 @@ + (id)showPickerWithTitle:(NSString *)title return picker; } ++ (instancetype)showPickerWithTitle:(NSString *)title + datePickerMode:(UIDatePickerMode)datePickerMode + selectedDate:(NSDate *)selectedDate + minimumDate:(NSDate *)minimumDate + maximumDate:(NSDate *)maximumDate + doneBlock:(ActionDateDoneBlock)doneBlock + cancelBlock:(ActionDateCancelBlock)cancelBlock + origin:(UIView*)view +{ + ActionSheetDatePicker* picker = [[ActionSheetDatePicker alloc] initWithTitle:title + datePickerMode:datePickerMode + selectedDate:selectedDate + doneBlock:doneBlock + cancelBlock:cancelBlock + origin:view]; + [picker setMinimumDate:minimumDate]; + [picker setMaximumDate:maximumDate]; + [picker showActionSheetPicker]; + return picker; +} - (id)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin { @@ -72,14 +107,34 @@ - (id)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePicke return self; } -- (id)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction +- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate target:(id)target action:(SEL)action origin:(id)origin +{ + self = [self initWithTitle:title datePickerMode:datePickerMode selectedDate:selectedDate target:target action:action origin:origin cancelAction:nil]; + self.minimumDate = minimumDate; + self.maximumDate = maximumDate; + return self; +} + +- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction +{ + self = [super initWithTarget:target successAction:action cancelAction:cancelAction origin:origin]; + if (self) { + self.title = title; + self.datePickerMode = datePickerMode; + self.selectedDate = selectedDate; + } + return self; +} + +- (instancetype)initWithTitle:(NSString *)title datePickerMode:(UIDatePickerMode)datePickerMode selectedDate:(NSDate *)selectedDate minimumDate:(NSDate *)minimumDate maximumDate:(NSDate *)maximumDate target:(id)target action:(SEL)action cancelAction:(SEL)cancelAction origin:(id)origin { self = [super initWithTarget:target successAction:action cancelAction:cancelAction origin:origin]; if (self) { self.title = title; self.datePickerMode = datePickerMode; self.selectedDate = selectedDate; - self.duration = 60; + self.minimumDate = minimumDate; + self.maximumDate = maximumDate; } return self; } @@ -109,13 +164,25 @@ - (UIView *)configuredPickerView { datePicker.calendar = self.calendar; datePicker.timeZone = self.timeZone; datePicker.locale = self.locale; - - [datePicker setDate:self.selectedDate animated:NO]; + + // if datepicker is set with a date in countDownMode then + // 1h is added to the initial countdown + if (self.datePickerMode == UIDatePickerModeCountDownTimer) { + datePicker.countDownDuration = self.countDownDuration; + // Due to a bug in UIDatePicker, countDownDuration needs to be set asynchronously + // more info: http://stackoverflow.com/a/20204317/1161723 + dispatch_async(dispatch_get_main_queue(), ^{ + datePicker.countDownDuration = self.countDownDuration; + }); + } else { + [datePicker setDate:self.selectedDate animated:NO]; + } + [datePicker addTarget:self action:@selector(eventForDatePicker:) forControlEvents:UIControlEventValueChanged]; - + //need to keep a reference to the picker so we can clear the DataSource / Delegate when dismissing (not used in this picker, but just in case somebody uses this as a template for another picker) self.pickerView = datePicker; - + return datePicker; } @@ -123,20 +190,25 @@ - (void)notifyTarget:(id)target didSucceedWithAction:(SEL)action origin:(id)orig { if (self.onActionSheetDone) { - self.onActionSheetDone(self, self.selectedDate, origin); + if (self.datePickerMode == UIDatePickerModeCountDownTimer) + self.onActionSheetDone(self, @(((UIDatePicker *)self.pickerView).countDownDuration), origin); + else + self.onActionSheetDone(self, self.selectedDate, origin); + return; } else if ([target respondsToSelector:action]) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" if (self.datePickerMode == UIDatePickerModeCountDownTimer) { - [target performSelector:action withObject:@(self.duration) withObject:origin]; + [target performSelector:action withObject:@(((UIDatePicker *)self.pickerView).countDownDuration) withObject:origin]; + } else { [target performSelector:action withObject:self.selectedDate withObject:origin]; } #pragma clang diagnostic pop - else - NSAssert(NO, @"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker", object_getClassName(target), sel_getName(action)); + else + NSAssert(NO, @"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker", object_getClassName(target), sel_getName(action)); } - (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin @@ -162,19 +234,39 @@ - (void)eventForDatePicker:(id)sender return; UIDatePicker *datePicker = (UIDatePicker *)sender; self.selectedDate = datePicker.date; - self.duration = datePicker.countDownDuration; + self.countDownDuration = datePicker.countDownDuration; } - (void)customButtonPressed:(id)sender { UIBarButtonItem *button = (UIBarButtonItem*)sender; NSInteger index = button.tag; NSAssert((index >= 0 && index < self.customButtons.count), @"Bad custom button tag: %zd, custom button count: %zd", index, self.customButtons.count); - NSAssert([self.pickerView respondsToSelector:@selector(setDate:animated:)], @"Bad pickerView for ActionSheetDatePicker, doesn't respond to setDate:animated:"); NSDictionary *buttonDetails = (self.customButtons)[(NSUInteger) index]; - NSDate *itemValue = buttonDetails[kButtonValue]; - UIDatePicker *picker = (UIDatePicker *)self.pickerView; - [picker setDate:itemValue animated:YES]; - [self eventForDatePicker:picker]; + NSAssert(buttonDetails != NULL, @"Custom button dictionary is invalid"); + + ActionType actionType = (ActionType) [buttonDetails[kActionType] integerValue]; + switch (actionType) { + case ActionTypeValue: { + NSAssert([self.pickerView respondsToSelector:@selector(setDate:animated:)], @"Bad pickerView for ActionSheetDatePicker, doesn't respond to setDate:animated:"); + NSDate *itemValue = buttonDetails[kButtonValue]; + UIDatePicker *picker = (UIDatePicker *)self.pickerView; + if (self.datePickerMode != UIDatePickerModeCountDownTimer) + { + [picker setDate:itemValue animated:YES]; + [self eventForDatePicker:picker]; + } + break; + } + + case ActionTypeBlock: + case ActionTypeSelector: + [super customButtonPressed:sender]; + break; + + default: + NSAssert(false, @"Unknown action type"); + break; + } } @end diff --git a/Libraries/Pickers/ActionSheetDistancePicker.h b/Libraries/Pickers/ActionSheetDistancePicker.h index c8a7863..f8f74e4 100644 --- a/Libraries/Pickers/ActionSheetDistancePicker.h +++ b/Libraries/Pickers/ActionSheetDistancePicker.h @@ -29,7 +29,11 @@ #import "DistancePickerView.h" @interface ActionSheetDistancePicker : AbstractActionSheetPicker -+ (id)showPickerWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString*)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin; ++ (instancetype)showPickerWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin; -- (id)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString*)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin; +- (instancetype)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin; + ++ (instancetype)showPickerWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction; + +- (instancetype)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction; @end diff --git a/Libraries/Pickers/ActionSheetDistancePicker.m b/Libraries/Pickers/ActionSheetDistancePicker.m index d8c291d..c9abcb9 100644 --- a/Libraries/Pickers/ActionSheetDistancePicker.m +++ b/Libraries/Pickers/ActionSheetDistancePicker.m @@ -41,13 +41,13 @@ @interface ActionSheetDistancePicker() @implementation ActionSheetDistancePicker -+ (id)showPickerWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString*)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin { - ActionSheetDistancePicker *picker = [[ActionSheetDistancePicker alloc] initWithTitle:title bigUnitString:bigUnitString bigUnitMax:bigUnitMax selectedBigUnit:selectedBigUnit smallUnitString:smallUnitString smallUnitMax:smallUnitMax selectedSmallUnit:selectedSmallUnit target:target action:action origin:origin]; ++ (instancetype)showPickerWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin { + ActionSheetDistancePicker *picker = [[ActionSheetDistancePicker alloc] initWithTitle:title bigUnitString:bigUnitString bigUnitMax:bigUnitMax selectedBigUnit:selectedBigUnit smallUnitString:smallUnitString smallUnitMax:smallUnitMax selectedSmallUnit:selectedSmallUnit target:target action:action origin:origin]; [picker showActionSheetPicker]; return picker; } -- (id)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString*)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin { +- (instancetype)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin { self = [super initWithTarget:target successAction:action cancelAction:nil origin:origin]; if (self) { self.title = title; @@ -63,6 +63,30 @@ - (id)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bi return self; } ++ (instancetype)showPickerWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction +{ + ActionSheetDistancePicker *picker = [[ActionSheetDistancePicker alloc] initWithTitle:title bigUnitString:bigUnitString bigUnitMax:bigUnitMax selectedBigUnit:selectedBigUnit smallUnitString:smallUnitString smallUnitMax:smallUnitMax selectedSmallUnit:selectedSmallUnit target:target action:action origin:origin cancelAction:cancelAction]; + [picker showActionSheetPicker]; + return picker; +} + +- (instancetype)initWithTitle:(NSString *)title bigUnitString:(NSString *)bigUnitString bigUnitMax:(NSInteger)bigUnitMax selectedBigUnit:(NSInteger)selectedBigUnit smallUnitString:(NSString *)smallUnitString smallUnitMax:(NSInteger)smallUnitMax selectedSmallUnit:(NSInteger)selectedSmallUnit target:(id)target action:(SEL)action origin:(id)origin cancelAction:(SEL)cancelAction +{ + self = [super initWithTarget:target successAction:action cancelAction:cancelAction origin:origin]; + if (self) { + self.title = title; + self.bigUnitString = bigUnitString; + self.bigUnitMax = bigUnitMax; + self.selectedBigUnit = selectedBigUnit; + self.smallUnitString = smallUnitString; + self.smallUnitMax = smallUnitMax; + self.selectedSmallUnit = selectedSmallUnit; + self.bigUnitDigits = [[NSString stringWithFormat:@"%li", (long)self.bigUnitMax] length]; + self.smallUnitDigits = [[NSString stringWithFormat:@"%li", (long)self.smallUnitMax] length]; + } + return self; +} + - (UIView *)configuredPickerView { CGRect distancePickerFrame = CGRectMake(0, 40, self.viewSize.width, 216); diff --git a/Libraries/Pickers/ActionSheetLocalePicker.m b/Libraries/Pickers/ActionSheetLocalePicker.m index b9b0bb5..05308be 100644 --- a/Libraries/Pickers/ActionSheetLocalePicker.m +++ b/Libraries/Pickers/ActionSheetLocalePicker.m @@ -178,14 +178,21 @@ - (void)setSelectedRows string = [[NSTimeZone localTimeZone] name]; NSArray *array = [string componentsSeparatedByString:@"/"]; - - if (array.count == 2) + if (array.count == 1) + { + // Unknown time zone - appeared only in travis builds. + self.selectedContinent = _continents[0]; + self.selectedCity = [self getCitiesByContinent:self.selectedContinent][0]; + } + else if (array.count == 2) { self.selectedContinent = array[0]; self.selectedCity = array[1]; } else + { assert(NO); + } } @@ -304,7 +311,8 @@ - (UIView *)pickerView:(UIPickerView *)pickerView pickerLabel = [[UILabel alloc] initWithFrame:frame]; [pickerLabel setTextAlignment:NSTextAlignmentCenter]; - [pickerLabel setMinimumScaleFactor:0.5]; + if ([pickerLabel respondsToSelector:@selector(setMinimumScaleFactor:)]) + [pickerLabel setMinimumScaleFactor:0.5]; [pickerLabel setAdjustsFontSizeToFitWidth:YES]; [pickerLabel setBackgroundColor:[UIColor clearColor]]; [pickerLabel setFont:[UIFont systemFontOfSize:20]]; @@ -367,14 +375,31 @@ - (void)customButtonPressed:(id)sender { UIBarButtonItem *button = (UIBarButtonItem*)sender; NSInteger index = button.tag; NSAssert((index >= 0 && index < self.customButtons.count), @"Bad custom button tag: %ld, custom button count: %lu", (long)index, (unsigned long)self.customButtons.count); + NSDictionary *buttonDetails = (self.customButtons)[(NSUInteger) index]; - id itemValue = buttonDetails[kButtonValue]; - if ( [itemValue isKindOfClass:[NSTimeZone class]] ) - { - NSTimeZone *timeZone = (NSTimeZone *) itemValue; - self.initialTimeZone = timeZone; - [self setSelectedRows]; - [self selectCurrentLocale:(UIPickerView *) self.pickerView]; + NSAssert(buttonDetails != NULL, @"Custom button dictionary is invalid"); + + ActionType actionType = (ActionType) [buttonDetails[kActionType] intValue]; + switch (actionType) { + case ActionTypeValue: { + id itemValue = buttonDetails[kButtonValue]; + if ( [itemValue isKindOfClass:[NSTimeZone class]] ) + { + NSTimeZone *timeZone = (NSTimeZone *) itemValue; + self.initialTimeZone = timeZone; + [self setSelectedRows]; + [self selectCurrentLocale:(UIPickerView *) self.pickerView]; + } + break; + } + + case ActionTypeBlock: + case ActionTypeSelector: + [super customButtonPressed:sender]; + break; + default: + NSAssert(false, @"Unknown action type"); + break; } } diff --git a/Libraries/Pickers/ActionSheetMultipleStringPicker.h b/Libraries/Pickers/ActionSheetMultipleStringPicker.h new file mode 100644 index 0000000..fcf35bf --- /dev/null +++ b/Libraries/Pickers/ActionSheetMultipleStringPicker.h @@ -0,0 +1,65 @@ +// +// ActionSheetMultipleStringPicker.h +// CoreActionSheetPicker +// +// Created by Alejandro on 21/07/15. +// Copyright (c) 2015 Petr Korolev. All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import "AbstractActionSheetPicker.h" + +@class ActionSheetMultipleStringPicker; +typedef void(^ActionMultipleStringDoneBlock)(ActionSheetMultipleStringPicker *picker, NSArray *selectedIndexes, id selectedValues); +typedef void(^ActionMultipleStringCancelBlock)(ActionSheetMultipleStringPicker *picker); + +@interface ActionSheetMultipleStringPicker : AbstractActionSheetPicker +/** + * Create and display an action sheet picker. + * + * @param title Title label for picker + * @param data is an array of strings to use for the picker's available selection choices + * @param index is used to establish the initially selected row; + * @param target must not be empty. It should respond to "onSuccess" actions. + * @param successAction + * @param cancelActionOrNil cancelAction + * @param origin must not be empty. It can be either an originating container view or a UIBarButtonItem to use with a popover arrow. + * + * @return return instance of picker + */ ++ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSArray *)indexes target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin; + +// Create an action sheet picker, but don't display until a subsequent call to "showActionPicker". Receiver must release the picker when ready. */ +- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSArray *)indexes target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin; + + + ++ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSArray *)indexes doneBlock:(ActionMultipleStringDoneBlock)doneBlock cancelBlock:(ActionMultipleStringCancelBlock)cancelBlock origin:(id)origin; + +- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSArray *)indexes doneBlock:(ActionMultipleStringDoneBlock)doneBlock cancelBlock:(ActionMultipleStringCancelBlock)cancelBlockOrNil origin:(id)origin; + +@property (nonatomic, copy) ActionMultipleStringDoneBlock onActionSheetDone; +@property (nonatomic, copy) ActionMultipleStringCancelBlock onActionSheetCancel; + +@end diff --git a/Libraries/Pickers/ActionSheetMultipleStringPicker.m b/Libraries/Pickers/ActionSheetMultipleStringPicker.m new file mode 100644 index 0000000..3ba6e1f --- /dev/null +++ b/Libraries/Pickers/ActionSheetMultipleStringPicker.m @@ -0,0 +1,199 @@ +// +// ActionSheetMultipleStringPicker.m +// CoreActionSheetPicker +// +// Created by Alejandro on 21/07/15. +// Copyright (c) 2015 Petr Korolev. All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import "ActionSheetMultipleStringPicker.h" + +@interface ActionSheetMultipleStringPicker() +@property (nonatomic,strong) NSArray *data; //Array of string arrays :) +@property (nonatomic,strong) NSArray *initialSelection; +@end + +@implementation ActionSheetMultipleStringPicker + ++ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSArray *)indexes doneBlock:(ActionMultipleStringDoneBlock)doneBlock cancelBlock:(ActionMultipleStringCancelBlock)cancelBlockOrNil origin:(id)origin { + ActionSheetMultipleStringPicker * picker = [[ActionSheetMultipleStringPicker alloc] initWithTitle:title rows:strings initialSelection:indexes doneBlock:doneBlock cancelBlock:cancelBlockOrNil origin:origin]; + [picker showActionSheetPicker]; + return picker; +} + +- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSArray *)indexes doneBlock:(ActionMultipleStringDoneBlock)doneBlock cancelBlock:(ActionMultipleStringCancelBlock)cancelBlockOrNil origin:(id)origin { + self = [self initWithTitle:title rows:strings initialSelection:indexes target:nil successAction:nil cancelAction:nil origin:origin]; + if (self) { + self.onActionSheetDone = doneBlock; + self.onActionSheetCancel = cancelBlockOrNil; + } + return self; +} + ++ (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSArray *)indexes target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin { + ActionSheetMultipleStringPicker *picker = [[ActionSheetMultipleStringPicker alloc] initWithTitle:title rows:data initialSelection:indexes target:target successAction:successAction cancelAction:cancelActionOrNil origin:origin]; + [picker showActionSheetPicker]; + return picker; +} + +- (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSArray *)indexes target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin { + self = [self initWithTarget:target successAction:successAction cancelAction:cancelActionOrNil origin:origin]; + if (self) { + self.data = data; + self.initialSelection = indexes; + self.title = title; + } + return self; +} + + +- (UIView *)configuredPickerView { + if (!self.data) + return nil; + CGRect pickerFrame = CGRectMake(0, 40, self.viewSize.width, 216); + UIPickerView *stringPicker = [[UIPickerView alloc] initWithFrame:pickerFrame]; + stringPicker.delegate = self; + stringPicker.dataSource = self; + + [self performInitialSelectionInPickerView:stringPicker]; + + if (self.data.count == 0) { + stringPicker.showsSelectionIndicator = NO; + stringPicker.userInteractionEnabled = NO; + } else { + stringPicker.showsSelectionIndicator = YES; + stringPicker.userInteractionEnabled = YES; + } + + //need to keep a reference to the picker so we can clear the DataSource / Delegate when dismissing + self.pickerView = stringPicker; + + return stringPicker; +} + +- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin { + if (self.onActionSheetDone) { + _onActionSheetDone(self, [self selectedIndexes], [self selection]); + return; + } + else if (target && [target respondsToSelector:successAction]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [target performSelector:successAction withObject:self.selectedIndexes withObject:origin]; +#pragma clang diagnostic pop + return; + } + NSLog(@"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker and done block is nil.", object_getClassName(target), sel_getName(successAction)); +} + +- (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin { + if (self.onActionSheetCancel) { + _onActionSheetCancel(self); + return; + } + else if (target && cancelAction && [target respondsToSelector:cancelAction]) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" + [target performSelector:cancelAction withObject:origin]; +#pragma clang diagnostic pop + } +} + +#pragma mark - UIPickerViewDelegate / DataSource + +- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { + +} + +- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { + return [self.data count]; +} + +- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { + return ((NSArray *)self.data[component]).count; +} + +- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { + id obj = (self.data)[(NSUInteger) row]; + + // return the object if it is already a NSString, + // otherwise, return the description, just like the toString() method in Java + // else, return nil to prevent exception + + if ([obj isKindOfClass:[NSString class]]) + return obj; + + if ([obj respondsToSelector:@selector(description)]) + return [obj performSelector:@selector(description)]; + + return nil; +} + +- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component { + id obj = (self.data)[component][(NSUInteger) row]; + + // return the object if it is already a NSString, + // otherwise, return the description, just like the toString() method in Java + // else, return nil to prevent exception + + if ([obj isKindOfClass:[NSString class]]) + return [[NSAttributedString alloc] initWithString:obj attributes:self.pickerTextAttributes]; + + if ([obj respondsToSelector:@selector(description)]) + return [[NSAttributedString alloc] initWithString:[obj performSelector:@selector(description)] attributes:self.pickerTextAttributes]; + + return nil; +} + +- (void)performInitialSelectionInPickerView:(UIPickerView *)pickerView { + for (int i = 0; i < self.selectedIndexes.count; i++) { + NSInteger row = [(NSNumber *)self.initialSelection[i] integerValue]; + [pickerView selectRow:row inComponent:i animated:NO]; + } +} + +- (NSArray *)selection { + NSMutableArray * array = [NSMutableArray array]; + for (int i = 0; i < self.data.count; i++) { + id object = self.data[i][[(UIPickerView *)self.pickerView selectedRowInComponent:(NSInteger)i]]; + [array addObject: object]; + } + return [array copy]; +} + +- (NSArray *)selectedIndexes { + NSMutableArray * indexes = [NSMutableArray array]; + for (int i = 0; i < self.data.count; i++) { + NSNumber *index = [NSNumber numberWithInteger:[(UIPickerView *)self.pickerView selectedRowInComponent:(NSInteger)i]]; + [indexes addObject: index]; + } + return [indexes copy]; +} + +//- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component { +// return pickerView.frame.size.width - 30; +//} + +@end diff --git a/Libraries/Pickers/ActionSheetPicker.h b/Libraries/Pickers/ActionSheetPicker.h new file mode 100644 index 0000000..69c67ee --- /dev/null +++ b/Libraries/Pickers/ActionSheetPicker.h @@ -0,0 +1,35 @@ +// +//Copyright (c) 2011, Tim Cinel +//All rights reserved. +// +//Redistribution and use in source and binary forms, with or without +//modification, are permitted provided that the following conditions are met: +//* Redistributions of source code must retain the above copyright +//notice, this list of conditions and the following disclaimer. +//* Redistributions in binary form must reproduce the above copyright +//notice, this list of conditions and the following disclaimer in the +//documentation and/or other materials provided with the distribution. +//* Neither the name of the nor the +//names of its contributors may be used to endorse or promote products +//derived from this software without specific prior written permission. +// +//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +//ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +//WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +//DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +//DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +//(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +//ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +//(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +//SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// + +#import "ActionSheetCustomPickerDelegate.h" +#import "AbstractActionSheetPicker.h" +#import "ActionSheetCustomPicker.h" +#import "ActionSheetDatePicker.h" +#import "ActionSheetDistancePicker.h" +#import "ActionSheetLocalePicker.h" +#import "ActionSheetStringPicker.h" +#import "ActionSheetMultipleStringPicker.h" \ No newline at end of file diff --git a/Libraries/Pickers/ActionSheetStringPicker.m b/Libraries/Pickers/ActionSheetStringPicker.m index da6d464..8849b17 100644 --- a/Libraries/Pickers/ActionSheetStringPicker.m +++ b/Libraries/Pickers/ActionSheetStringPicker.m @@ -81,14 +81,14 @@ - (UIView *)configuredPickerView { stringPicker.showsSelectionIndicator = YES; stringPicker.userInteractionEnabled = YES; } - + //need to keep a reference to the picker so we can clear the DataSource / Delegate when dismissing self.pickerView = stringPicker; - + return stringPicker; } -- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin { +- (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin { if (self.onActionSheetDone) { id selectedObject = (self.data.count > 0) ? (self.data)[(NSUInteger) self.selectedIndex] : nil; _onActionSheetDone(self, self.selectedIndex, selectedObject); @@ -101,7 +101,7 @@ - (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:( #pragma clang diagnostic pop return; } - NSLog(@"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker", object_getClassName(target), sel_getName(successAction)); + NSLog(@"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker and done block is nil.", object_getClassName(target), sel_getName(successAction)); } - (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin { @@ -143,12 +143,53 @@ - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row f if ([obj respondsToSelector:@selector(description)]) return [obj performSelector:@selector(description)]; + + return nil; +} +- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component { + id obj = (self.data)[(NSUInteger) row]; + + // return the object if it is already a NSString, + // otherwise, return the description, just like the toString() method in Java + // else, return nil to prevent exception + + if ([obj isKindOfClass:[NSString class]]) + return [[NSAttributedString alloc] initWithString:obj attributes:self.pickerTextAttributes]; + + if ([obj respondsToSelector:@selector(description)]) + return [[NSAttributedString alloc] initWithString:[obj performSelector:@selector(description)] attributes:self.pickerTextAttributes]; + return nil; } +- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { + UILabel *pickerLabel = (UILabel *)view; + if (pickerLabel == nil) { + pickerLabel = [[UILabel alloc] init]; + } + id obj = (self.data)[(NSUInteger) row]; + + NSAttributedString *attributeTitle = nil; + // use the object if it is already a NSString, + // otherwise, use the description, just like the toString() method in Java + // else, use String with no text to ensure this delegate do not return a nil value. + + if ([obj isKindOfClass:[NSString class]]) + attributeTitle = [[NSAttributedString alloc] initWithString:obj attributes:self.pickerTextAttributes]; + + if ([obj respondsToSelector:@selector(description)]) + attributeTitle = [[NSAttributedString alloc] initWithString:[obj performSelector:@selector(description)] attributes:self.pickerTextAttributes]; + + if (attributeTitle == nil) { + attributeTitle = [[NSAttributedString alloc] initWithString:@"" attributes:self.pickerTextAttributes]; + } + pickerLabel.attributedText = attributeTitle; + return pickerLabel; +} + - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component { return pickerView.frame.size.width - 30; } -@end \ No newline at end of file +@end diff --git a/Libraries/Pickers/DistancePickerView.m b/Libraries/Pickers/DistancePickerView.m index 88036f7..72bfcc5 100644 --- a/Libraries/Pickers/DistancePickerView.m +++ b/Libraries/Pickers/DistancePickerView.m @@ -15,7 +15,7 @@ @implementation DistancePickerView -- (id)initWithFrame:(CGRect)frame +- (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; diff --git a/Libraries/Pickers/SWActionSheet.h b/Libraries/Pickers/SWActionSheet.h index 0c2609d..91d531f 100644 --- a/Libraries/Pickers/SWActionSheet.h +++ b/Libraries/Pickers/SWActionSheet.h @@ -13,7 +13,7 @@ - (void)showFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated; -- (id)initWithView:(UIView *)view; +- (instancetype)initWithView:(UIView *)view; - (void)showInContainerView; @end \ No newline at end of file diff --git a/Libraries/Pickers/SWActionSheet.m b/Libraries/Pickers/SWActionSheet.m index 2869d53..fcccbe3 100644 --- a/Libraries/Pickers/SWActionSheet.m +++ b/Libraries/Pickers/SWActionSheet.m @@ -5,11 +5,9 @@ #import "SWActionSheet.h" -static UIWindow *SWActionSheetWindow = nil; - static const float delay = 0.f; -static const float duration = .3f; +static const float duration = .25f; static const enum UIViewAnimationOptions options = UIViewAnimationOptionCurveEaseIn; @@ -22,6 +20,9 @@ @interface SWActionSheetVC : UIViewController @interface SWActionSheet () +{ + UIWindow *SWActionSheetWindow; +} @property (nonatomic, assign) BOOL presented; @@ -51,7 +52,7 @@ - (void)dismissWithClickedButtonIndex:(int)i animated:(BOOL)animated void (^completion)(BOOL) = ^(BOOL finished) { // if (![appWindow isKeyWindow]) // [appWindow makeKeyAndVisible]; - [SWActionSheet destroyWindow]; + [self destroyWindow]; [self removeFromSuperview]; }; // Do actions animated or not @@ -64,32 +65,40 @@ - (void)dismissWithClickedButtonIndex:(int)i animated:(BOOL)animated self.presented = NO; } -+ (void)destroyWindow +- (void)destroyWindow { if (SWActionSheetWindow) { - [SWActionSheet actionSheetContainer].actionSheet = nil; + [self actionSheetContainer].actionSheet = nil; SWActionSheetWindow.hidden = YES; if ([SWActionSheetWindow isKeyWindow]) [SWActionSheetWindow resignFirstResponder]; + SWActionSheetWindow.rootViewController = nil; SWActionSheetWindow = nil; } } -+ (UIWindow *)window +- (UIWindow *)window { - return (SWActionSheetWindow ?: (SWActionSheetWindow = ({ - UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; - window.windowLevel = UIWindowLevelAlert; - window.backgroundColor = [UIColor clearColor]; - window.rootViewController = [SWActionSheetVC new]; - window; - }))); + if ( SWActionSheetWindow ) + { + return SWActionSheetWindow; + } + else + { + return SWActionSheetWindow = ({ + UIWindow *window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; + window.windowLevel = UIWindowLevelAlert; + window.backgroundColor = [UIColor clearColor]; + window.rootViewController = [SWActionSheetVC new]; + window; + }); + } } -+ (SWActionSheetVC *)actionSheetContainer +- (SWActionSheetVC *)actionSheetContainer { - return (SWActionSheetVC *) [SWActionSheet window].rootViewController; + return (SWActionSheetVC *) [self window].rootViewController; } - (instancetype)initWithView:(UIView *)aView @@ -99,7 +108,7 @@ - (instancetype)initWithView:(UIView *)aView view = aView; self.backgroundColor = [UIColor colorWithWhite:0.f alpha:0.0f]; _bgView = [UIView new]; - _bgView.backgroundColor = [UIColor whiteColor]; + _bgView.backgroundColor = [UIColor colorWithRed:247.f/255.f green:247.f/255.f blue:247.f/255.f alpha:1.0f]; [self addSubview:_bgView]; [self addSubview:view]; } @@ -123,12 +132,12 @@ - (void)showFromBarButtonItem:(UIBarButtonItem *)item animated:(BOOL)animated - (void)showInContainerView { // Make sheet window visible and active - UIWindow *sheetWindow = [SWActionSheet window]; + UIWindow *sheetWindow = [self window]; if (![sheetWindow isKeyWindow]) [sheetWindow makeKeyAndVisible]; sheetWindow.hidden = NO; // Put our ActionSheet in Container (it will be presented as soon as possible) - [SWActionSheet actionSheetContainer].actionSheet = self; + self.actionSheetContainer.actionSheet = self; } - (void)showInContainerViewAnimated:(BOOL)animated @@ -156,6 +165,11 @@ - (void)showInContainerViewAnimated:(BOOL)animated @implementation SWActionSheetVC + +- (UIStatusBarStyle)preferredStatusBarStyle { + return [UIApplication sharedApplication].statusBarStyle; +} + - (void)setActionSheet:(SWActionSheet *)actionSheet { // Prevent processing one action sheet twice @@ -188,4 +202,20 @@ - (void)presentActionSheetAnimated:(BOOL)animated } } +- (BOOL)prefersStatusBarHidden { + return [UIApplication sharedApplication].statusBarHidden; +} + +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation +{ + return NO; +} + +// iOS6 support +// --- +- (BOOL)shouldAutorotate +{ + return YES; +} + @end diff --git a/Libraries/SSTextView/SSTextView.m b/Libraries/SSTextView/SSTextView.m index a580f81..00bddce 100644 --- a/Libraries/SSTextView/SSTextView.m +++ b/Libraries/SSTextView/SSTextView.m @@ -77,7 +77,7 @@ - (void)drawRect:(CGRect)rect { if (_shouldDrawPlaceholder) { [_placeholderColor set]; - [_placeholder drawInRect:CGRectMake(8.0f, 8.0f, self.frame.size.width - 16.0f, self.frame.size.height - 16.0f) withFont:self.font]; + [_placeholder drawInRect:CGRectMake(8.0f, 8.0f, self.frame.size.width - 16.0f, self.frame.size.height - 16.0f) withAttributes:@{ NSFontAttributeName:self.font }]; } } @@ -106,4 +106,4 @@ - (void)_textChanged:(NSNotification *)notificaiton { [self _updateShouldDrawPlaceholder]; } -@end \ No newline at end of file +@end diff --git a/Protocols/TaskBag.h b/Protocols/TaskBag.h index 0a953c1..ccbe92b 100644 --- a/Protocols/TaskBag.h +++ b/Protocols/TaskBag.h @@ -62,7 +62,7 @@ - (NSUInteger) indexOfTask:(Task*)task; - (NSArray*) tasksWithFilter:(id)filter withSortOrder:(Sort*)sortOrder; -@property (readonly) int size; +@property (readonly) NSUInteger size; @property (nonatomic, readonly) NSArray *tasks; @property (nonatomic, readonly) NSArray *projects; @property (nonatomic, readonly) NSArray *contexts; diff --git a/Todo-txt-unit-tests/Todo-txt-unit-tests-Info.plist b/Todo-txt-unit-tests/Todo-txt-unit-tests-Info.plist index b022486..169b6f7 100644 --- a/Todo-txt-unit-tests/Todo-txt-unit-tests-Info.plist +++ b/Todo-txt-unit-tests/Todo-txt-unit-tests-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.todotxt.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType diff --git a/View Controllers/TaskEditViewController.m b/View Controllers/TaskEditViewController.m index 62aceed..2682adb 100644 --- a/View Controllers/TaskEditViewController.m +++ b/View Controllers/TaskEditViewController.m @@ -186,7 +186,7 @@ - (void)viewDidLoad { CGRect frame = CGRectMake(0, 0, 320, 300); UIViewController *vc = [[UIViewController alloc] init]; - vc.contentSizeForViewInPopover = frame.size; + vc.preferredContentSize = frame.size; vc.view.frame = frame; vc.view.backgroundColor = [UIColor blackColor]; @@ -358,12 +358,8 @@ - (IBAction)helpButtonPressed:(id)sender { [animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]]; [[self.view layer] addAnimation:animation forKey:kCATransitionReveal]; - CGSize size; - if (self.interfaceOrientation == UIDeviceOrientationPortrait) { - size = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height); - } else { - size = CGSizeMake(self.view.frame.size.height, self.view.frame.size.width); - } + CGSize size = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height); + const CGRect rect = (CGRect){CGPointZero,size}; self.helpView.frame = rect; self.helpCloseButton.hidden = NO; @@ -391,7 +387,7 @@ - (IBAction)helpCloseButtonPressed:(id)sender { [self.textView becomeFirstResponder]; } -- (void) priorityWasSelected:(NSInteger *)selectedIndex element:(id)element { +- (void) priorityWasSelected:(NSInteger)selectedIndex element:(id)element { self.actionSheetPicker = nil; if (selectedIndex >= 0) { Priority *selectedPriority = [Priority byName:(PriorityName)selectedIndex]; @@ -410,7 +406,7 @@ - (void) priorityWasSelected:(NSInteger *)selectedIndex element:(id)element { [self.textView becomeFirstResponder]; } -- (void) projectWasSelected:(NSInteger *)selectedIndex element:(id)element { +- (void) projectWasSelected:(NSInteger)selectedIndex element:(id)element { self.actionSheetPicker = nil; if (selectedIndex >= 0) { id taskBag = self.appDelegate.taskBag; @@ -427,7 +423,7 @@ - (void) projectWasSelected:(NSInteger *)selectedIndex element:(id)element { [self.textView becomeFirstResponder]; } -- (void) contextWasSelected:(NSInteger *)selectedIndex element:(id)element { +- (void) contextWasSelected:(NSInteger)selectedIndex element:(id)element { self.actionSheetPicker = nil; if (selectedIndex >= 0) { id taskBag = self.appDelegate.taskBag; diff --git a/View Controllers/TasksViewController.m b/View Controllers/TasksViewController.m index a80f329..e516adc 100644 --- a/View Controllers/TasksViewController.m +++ b/View Controllers/TasksViewController.m @@ -469,7 +469,7 @@ - (void)settingsViewController:(IASKAppSettingsViewController*)sender buttonTapp [alert show]; } else if([key isEqualToString:@"about_todo"]) { - NSURL *url = [NSURL URLWithString:@"http://todotxt.com"]; + NSURL *url = [NSURL URLWithString:@"http://todotxt.org/"]; [[UIApplication sharedApplication] openURL:url]; } } diff --git a/Views/TaskCell.m b/Views/TaskCell.m index bc75fb6..801ae3b 100644 --- a/Views/TaskCell.m +++ b/Views/TaskCell.m @@ -340,7 +340,7 @@ + (TaskCell *)staticSizingCell { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - _staticSizingCell = [[TaskCell alloc] initWithStyle:UITableViewStylePlain reuseIdentifier:nil]; + _staticSizingCell = [[TaskCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; }); return _staticSizingCell; diff --git a/todo.txt-touch-ios.xcodeproj/project.pbxproj b/todo.txt-touch-ios.xcodeproj/project.pbxproj index eb3376a..d75b94d 100755 --- a/todo.txt-touch-ios.xcodeproj/project.pbxproj +++ b/todo.txt-touch-ios.xcodeproj/project.pbxproj @@ -17,6 +17,8 @@ 0F75B4321499141800848E27 /* TaskUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F75B4301499141800848E27 /* TaskUtil.m */; }; 0F75B433149916D900848E27 /* ContextParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 882B3E8413EF46740085C888 /* ContextParser.m */; }; 0F75B434149923E700848E27 /* ProjectParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 882B3E8D13EF47B70085C888 /* ProjectParser.m */; }; + 0F85520B1F4F2A22006E804E /* ActionSheetMultipleStringPicker.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F8552091F4F2A22006E804E /* ActionSheetMultipleStringPicker.m */; }; + 0F85520D1F4F2A88006E804E /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F85520C1F4F2A88006E804E /* CoreImage.framework */; }; 1D3623260D0F684500981E51 /* TodoTxtAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* TodoTxtAppDelegate.m */; }; 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; @@ -198,7 +200,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 0F75B415149912DF00848E27 /* Todo-txt-unit-tests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Todo-txt-unit-tests.octest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 0F75B415149912DF00848E27 /* Todo-txt-unit-tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Todo-txt-unit-tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 0F75B41D149912DF00848E27 /* Todo-txt-unit-tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Todo-txt-unit-tests-Info.plist"; sourceTree = ""; }; 0F75B41F149912DF00848E27 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 0F75B421149912DF00848E27 /* TaskUtilTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TaskUtilTest.h; sourceTree = ""; }; @@ -206,6 +208,10 @@ 0F75B425149912DF00848E27 /* Todo-txt-unit-tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Todo-txt-unit-tests-Prefix.pch"; sourceTree = ""; }; 0F75B42F1499141800848E27 /* TaskUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TaskUtil.h; sourceTree = ""; }; 0F75B4301499141800848E27 /* TaskUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TaskUtil.m; sourceTree = ""; }; + 0F8552081F4F2A22006E804E /* ActionSheetMultipleStringPicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionSheetMultipleStringPicker.h; sourceTree = ""; }; + 0F8552091F4F2A22006E804E /* ActionSheetMultipleStringPicker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ActionSheetMultipleStringPicker.m; sourceTree = ""; }; + 0F85520A1F4F2A22006E804E /* ActionSheetPicker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionSheetPicker.h; sourceTree = ""; }; + 0F85520C1F4F2A88006E804E /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; }; 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 1D3623240D0F684500981E51 /* TodoTxtAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TodoTxtAppDelegate.h; sourceTree = ""; }; 1D3623250D0F684500981E51 /* TodoTxtAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TodoTxtAppDelegate.m; sourceTree = ""; }; @@ -477,6 +483,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 0F85520D1F4F2A88006E804E /* CoreImage.framework in Frameworks */, 888286AD146E52C5007DBB16 /* QuartzCore.framework in Frameworks */, F45C4F90145363F300E92C6D /* CoreText.framework in Frameworks */, 5910DBD114216A2300BB2D68 /* MessageUI.framework in Frameworks */, @@ -532,7 +539,7 @@ isa = PBXGroup; children = ( 1D6058910D05DD3D006BFB54 /* Todo.txt.app */, - 0F75B415149912DF00848E27 /* Todo-txt-unit-tests.octest */, + 0F75B415149912DF00848E27 /* Todo-txt-unit-tests.xctest */, ); name = Products; sourceTree = ""; @@ -605,6 +612,7 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( + 0F85520C1F4F2A88006E804E /* CoreImage.framework */, 88D5C2851519995C00C3744B /* DropboxSDK.framework */, 888286AC146E52C5007DBB16 /* QuartzCore.framework */, F45C4F8F145363F300E92C6D /* CoreText.framework */, @@ -878,6 +886,9 @@ 8810D7FA19ECC2DC00F954C3 /* Pickers */ = { isa = PBXGroup; children = ( + 0F8552081F4F2A22006E804E /* ActionSheetMultipleStringPicker.h */, + 0F8552091F4F2A22006E804E /* ActionSheetMultipleStringPicker.m */, + 0F85520A1F4F2A22006E804E /* ActionSheetPicker.h */, 8810D7FB19ECC2DC00F954C3 /* AbstractActionSheetPicker.h */, 8810D7FC19ECC2DC00F954C3 /* AbstractActionSheetPicker.m */, 8810D7FD19ECC2DC00F954C3 /* ActionSheetCustomPicker.h */, @@ -1045,7 +1056,7 @@ ); name = "Todo-txt-unit-tests"; productName = "Todo-txt-unit-tests"; - productReference = 0F75B415149912DF00848E27 /* Todo-txt-unit-tests.octest */; + productReference = 0F75B415149912DF00848E27 /* Todo-txt-unit-tests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; 1D6058900D05DD3D006BFB54 /* Todo.txt */ = { @@ -1073,7 +1084,7 @@ isa = PBXProject; attributes = { LastTestingUpgradeCheck = 0600; - LastUpgradeCheck = 0510; + LastUpgradeCheck = 0900; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "todo.txt-touch-ios" */; compatibilityVersion = "Xcode 3.2"; @@ -1302,6 +1313,7 @@ 5CE4235A17A602A4009C6D25 /* IASKPSSliderSpecifierViewCell.m in Sources */, 5CE4235C17A602A4009C6D25 /* IASKPSTextFieldSpecifierViewCell.m in Sources */, 5CE4235E17A602A4009C6D25 /* IASKPSTitleValueSpecifierViewCell.m in Sources */, + 0F85520B1F4F2A22006E804E /* ActionSheetMultipleStringPicker.m in Sources */, 5CE4236017A602A4009C6D25 /* IASKPSToggleSwitchSpecifierViewCell.m in Sources */, 5CE4236217A602A4009C6D25 /* IASKSlider.m in Sources */, 5CE4236417A602A4009C6D25 /* IASKSwitch.m in Sources */, @@ -1368,6 +1380,7 @@ "\"$(SRCROOT)/Libraries/OCMock\"", ); OTHER_LDFLAGS = "-all_load"; + PRODUCT_BUNDLE_IDENTIFIER = "com.todotxt.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -1395,6 +1408,7 @@ "\"$(SRCROOT)/Libraries/OCMock\"", ); OTHER_LDFLAGS = "-all_load"; + PRODUCT_BUNDLE_IDENTIFIER = "com.todotxt.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; VALIDATE_PRODUCT = YES; }; @@ -1423,6 +1437,7 @@ "\"$(SRCROOT)/Libraries/OCMock\"", ); OTHER_LDFLAGS = "-all_load"; + PRODUCT_BUNDLE_IDENTIFIER = "com.todotxt.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; VALIDATE_PRODUCT = YES; }; @@ -1451,13 +1466,14 @@ INFOPLIST_FILE = "todo_txt_touch_ios-Info.plist"; INFOPLIST_PREFIX_HEADER = DropboxApiKey.h; INFOPLIST_PREPROCESS = YES; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)\"", "\"$(SRCROOT)/Libraries/OCMock\"", ); OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "com.todotxt.${PRODUCT_NAME:rfc1034identifier}-Touch"; PRODUCT_NAME = Todo.txt; PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; @@ -1487,13 +1503,14 @@ INFOPLIST_FILE = "todo_txt_touch_ios-Info.plist"; INFOPLIST_PREFIX_HEADER = DropboxApiKey.h; INFOPLIST_PREPROCESS = YES; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)\"", "\"$(SRCROOT)/Libraries/OCMock\"", ); OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "com.todotxt.${PRODUCT_NAME:rfc1034identifier}-Touch"; PRODUCT_NAME = Todo.txt; PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; @@ -1506,13 +1523,35 @@ 331AF76414420EAD00EF329E /* Ad Hoc */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = Entitlements.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; PRODUCT_NAME = Todo.txt; PROVISIONING_PROFILE = ""; @@ -1543,13 +1582,14 @@ INFOPLIST_FILE = "todo_txt_touch_ios-Info.plist"; INFOPLIST_PREFIX_HEADER = DropboxApiKey.h; INFOPLIST_PREPROCESS = YES; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)\"", "\"$(SRCROOT)/Libraries/OCMock\"", ); OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "com.todotxt.${PRODUCT_NAME:rfc1034identifier}-Touch"; PRODUCT_NAME = Todo.txt; PROVISIONING_PROFILE = ""; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; @@ -1563,13 +1603,35 @@ 33536C1314A230180017DA57 /* AppStore */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = ""; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; PRODUCT_NAME = Todo.txt; PROVISIONING_PROFILE = ""; @@ -1599,13 +1661,14 @@ INFOPLIST_FILE = "todo_txt_touch_ios-Info.plist"; INFOPLIST_PREFIX_HEADER = DropboxApiKey.h; INFOPLIST_PREPROCESS = YES; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)\"", "\"$(SRCROOT)/Libraries/OCMock\"", ); OTHER_LDFLAGS = "-ObjC"; + PRODUCT_BUNDLE_IDENTIFIER = "com.todotxt.${PRODUCT_NAME:rfc1034identifier}-Touch"; PRODUCT_NAME = Todo.txt; PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; @@ -1638,6 +1701,7 @@ "\"$(SRCROOT)/Libraries/OCMock\"", ); OTHER_LDFLAGS = "-all_load"; + PRODUCT_BUNDLE_IDENTIFIER = "com.todotxt.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; VALIDATE_PRODUCT = YES; }; @@ -1646,13 +1710,36 @@ C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = ""; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = Todo.txt; PROVISIONING_PROFILE = ""; @@ -1664,13 +1751,35 @@ C01FCF5008A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_ENTITLEMENTS = ""; CODE_SIGN_IDENTITY = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = c99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; PRODUCT_NAME = Todo.txt; PROVISIONING_PROFILE = ""; diff --git a/todo_txt_touch_ios-Info.plist b/todo_txt_touch_ios-Info.plist index 6d2d90d..4c40dd5 100644 --- a/todo_txt_touch_ios-Info.plist +++ b/todo_txt_touch_ios-Info.plist @@ -78,7 +78,7 @@ CFBundleIdentifier - com.todotxt.${PRODUCT_NAME:rfc1034identifier}-Touch + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName