ActionSheetMultipleStringPicker.m 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. //
  2. // ActionSheetMultipleStringPicker.m
  3. // CoreActionSheetPicker
  4. //
  5. // Created by Alejandro on 21/07/15.
  6. // Copyright (c) 2015 Petr Korolev. All rights reserved.
  7. //
  8. //Redistribution and use in source and binary forms, with or without
  9. //modification, are permitted provided that the following conditions are met:
  10. //* Redistributions of source code must retain the above copyright
  11. //notice, this list of conditions and the following disclaimer.
  12. //* Redistributions in binary form must reproduce the above copyright
  13. //notice, this list of conditions and the following disclaimer in the
  14. //documentation and/or other materials provided with the distribution.
  15. //* Neither the name of the <organization> nor the
  16. //names of its contributors may be used to endorse or promote products
  17. //derived from this software without specific prior written permission.
  18. //
  19. //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  20. //ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. //WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. //DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  23. //DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. //(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. //åLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26. //ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. //(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. //SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. //
  30. #import "ActionSheetMultipleStringPicker.h"
  31. @interface ActionSheetMultipleStringPicker()
  32. @property (nonatomic,strong) NSArray *data; //Array of string arrays :)
  33. @property (nonatomic,strong) NSArray *initialSelection;
  34. @end
  35. @implementation ActionSheetMultipleStringPicker
  36. + (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSArray *)indexes doneBlock:(ActionMultipleStringDoneBlock)doneBlock cancelBlock:(ActionMultipleStringCancelBlock)cancelBlockOrNil origin:(id)origin {
  37. ActionSheetMultipleStringPicker * picker = [[ActionSheetMultipleStringPicker alloc] initWithTitle:title rows:strings initialSelection:indexes doneBlock:doneBlock cancelBlock:cancelBlockOrNil origin:origin];
  38. [picker showActionSheetPicker];
  39. return picker;
  40. }
  41. - (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)strings initialSelection:(NSArray *)indexes doneBlock:(ActionMultipleStringDoneBlock)doneBlock cancelBlock:(ActionMultipleStringCancelBlock)cancelBlockOrNil origin:(id)origin {
  42. self = [self initWithTitle:title rows:strings initialSelection:indexes target:nil successAction:nil cancelAction:nil origin:origin];
  43. if (self) {
  44. self.onActionSheetDone = doneBlock;
  45. self.onActionSheetCancel = cancelBlockOrNil;
  46. }
  47. return self;
  48. }
  49. + (instancetype)showPickerWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSArray *)indexes target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin {
  50. ActionSheetMultipleStringPicker *picker = [[ActionSheetMultipleStringPicker alloc] initWithTitle:title rows:data initialSelection:indexes target:target successAction:successAction cancelAction:cancelActionOrNil origin:origin];
  51. [picker showActionSheetPicker];
  52. return picker;
  53. }
  54. - (instancetype)initWithTitle:(NSString *)title rows:(NSArray *)data initialSelection:(NSArray *)indexes target:(id)target successAction:(SEL)successAction cancelAction:(SEL)cancelActionOrNil origin:(id)origin {
  55. self = [self initWithTarget:target successAction:successAction cancelAction:cancelActionOrNil origin:origin];
  56. if (self) {
  57. self.data = data;
  58. self.initialSelection = indexes;
  59. self.title = title;
  60. }
  61. return self;
  62. }
  63. - (UIView *)configuredPickerView {
  64. if (!self.data)
  65. return nil;
  66. CGRect pickerFrame = CGRectMake(0, 40, self.viewSize.width, 216);
  67. UIPickerView *stringPicker = [[UIPickerView alloc] initWithFrame:pickerFrame];
  68. stringPicker.delegate = self;
  69. stringPicker.dataSource = self;
  70. [self performInitialSelectionInPickerView:stringPicker];
  71. if (self.data.count == 0) {
  72. stringPicker.showsSelectionIndicator = NO;
  73. stringPicker.userInteractionEnabled = NO;
  74. } else {
  75. stringPicker.showsSelectionIndicator = YES;
  76. stringPicker.userInteractionEnabled = YES;
  77. }
  78. //need to keep a reference to the picker so we can clear the DataSource / Delegate when dismissing
  79. self.pickerView = stringPicker;
  80. return stringPicker;
  81. }
  82. - (void)notifyTarget:(id)target didSucceedWithAction:(SEL)successAction origin:(id)origin {
  83. if (self.onActionSheetDone) {
  84. _onActionSheetDone(self, [self selectedIndexes], [self selection]);
  85. return;
  86. }
  87. else if (target && [target respondsToSelector:successAction]) {
  88. #pragma clang diagnostic push
  89. #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
  90. [target performSelector:successAction withObject:self.selectedIndexes withObject:origin];
  91. #pragma clang diagnostic pop
  92. return;
  93. }
  94. NSLog(@"Invalid target/action ( %s / %s ) combination used for ActionSheetPicker and done block is nil.", object_getClassName(target), sel_getName(successAction));
  95. }
  96. - (void)notifyTarget:(id)target didCancelWithAction:(SEL)cancelAction origin:(id)origin {
  97. if (self.onActionSheetCancel) {
  98. _onActionSheetCancel(self);
  99. return;
  100. }
  101. else if (target && cancelAction && [target respondsToSelector:cancelAction]) {
  102. #pragma clang diagnostic push
  103. #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
  104. [target performSelector:cancelAction withObject:origin];
  105. #pragma clang diagnostic pop
  106. }
  107. }
  108. #pragma mark - UIPickerViewDelegate / DataSource
  109. - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
  110. }
  111. - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
  112. return [self.data count];
  113. }
  114. - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
  115. return ((NSArray *)self.data[component]).count;
  116. }
  117. - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
  118. id obj = (self.data)[(NSUInteger) row];
  119. // return the object if it is already a NSString,
  120. // otherwise, return the description, just like the toString() method in Java
  121. // else, return nil to prevent exception
  122. if ([obj isKindOfClass:[NSString class]])
  123. return obj;
  124. if ([obj respondsToSelector:@selector(description)])
  125. return [obj performSelector:@selector(description)];
  126. return nil;
  127. }
  128. - (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component {
  129. id obj = (self.data)[component][(NSUInteger) row];
  130. // return the object if it is already a NSString,
  131. // otherwise, return the description, just like the toString() method in Java
  132. // else, return nil to prevent exception
  133. if ([obj isKindOfClass:[NSString class]])
  134. return [[NSAttributedString alloc] initWithString:obj attributes:self.pickerTextAttributes];
  135. if ([obj respondsToSelector:@selector(description)])
  136. return [[NSAttributedString alloc] initWithString:[obj performSelector:@selector(description)] attributes:self.pickerTextAttributes];
  137. return nil;
  138. }
  139. - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
  140. UILabel *pickerLabel = (UILabel *)view;
  141. if (pickerLabel == nil) {
  142. pickerLabel = [[UILabel alloc] init];
  143. }
  144. id obj = (self.data)[component][row];
  145. NSAttributedString *attributeTitle = nil;
  146. // use the object if it is already a NSString,
  147. // otherwise, use the description, just like the toString() method in Java
  148. // else, use String with no text to ensure this delegate do not return a nil value.
  149. if ([obj isKindOfClass:[NSString class]])
  150. attributeTitle = [[NSAttributedString alloc] initWithString:obj attributes:self.pickerTextAttributes];
  151. if ([obj respondsToSelector:@selector(description)])
  152. attributeTitle = [[NSAttributedString alloc] initWithString:[obj performSelector:@selector(description)] attributes:self.pickerTextAttributes];
  153. if (attributeTitle == nil) {
  154. attributeTitle = [[NSAttributedString alloc] initWithString:@"" attributes:self.pickerTextAttributes];
  155. }
  156. pickerLabel.attributedText = attributeTitle;
  157. return pickerLabel;
  158. }
  159. - (void)performInitialSelectionInPickerView:(UIPickerView *)pickerView {
  160. for (int i = 0; i < self.selectedIndexes.count; i++) {
  161. NSInteger row = [(NSNumber *)self.initialSelection[i] integerValue];
  162. [pickerView selectRow:row inComponent:i animated:NO];
  163. }
  164. }
  165. - (NSArray *)selection {
  166. NSMutableArray * array = [NSMutableArray array];
  167. for (int i = 0; i < self.data.count; i++) {
  168. id object = self.data[i][[(UIPickerView *)self.pickerView selectedRowInComponent:(NSInteger)i]];
  169. [array addObject: object];
  170. }
  171. return [array copy];
  172. }
  173. - (NSArray *)selectedIndexes {
  174. NSMutableArray * indexes = [NSMutableArray array];
  175. for (int i = 0; i < self.data.count; i++) {
  176. NSNumber *index = [NSNumber numberWithInteger:[(UIPickerView *)self.pickerView selectedRowInComponent:(NSInteger)i]];
  177. [indexes addObject: index];
  178. }
  179. return [indexes copy];
  180. }
  181. //- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
  182. // return pickerView.frame.size.width - 30;
  183. //}
  184. @end