-
-
Notifications
You must be signed in to change notification settings - Fork 740
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added callback for custom button being pressed #81
Changes from 1 commit
e16b5be
8443a5a
2588541
f176272
ab80aff
0054e66
ed2673b
846d7cf
8331304
5e7a4fd
f240387
a983d3f
3a3f071
72462d6
8de1958
6ec33cb
4c60293
a79af0f
eab2f94
3015f82
fb35e25
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -230,38 +230,108 @@ - (void)dismissPicker | |
|
||
#pragma mark - Custom Buttons | ||
|
||
- (void)addCustomButtonWithTitle:(NSString *)title value:(id)value | ||
- (NSMutableArray *)customButtons | ||
{ | ||
if ( !self.customButtons ) | ||
if (!_customButtons) { | ||
_customButtons = [[NSMutableArray alloc] init]; | ||
} | ||
|
||
return _customButtons; | ||
} | ||
|
||
- (void)addCustomButtonWithTitle:(NSString *)title value:(id)value | ||
{ | ||
if ( !title ) | ||
title = @""; | ||
if ( !value ) | ||
value = @0; | ||
NSDictionary *buttonDetails = @{ | ||
kButtonTitle : title, | ||
kActionType : @(Value), | ||
kButtonValue : value | ||
}; | ||
[self.customButtons addObject:buttonDetails]; | ||
} | ||
|
||
- (void)addCustomButtonWithTitle:(NSString *)title actionBlock:(ActionBlock)block | ||
{ | ||
if (!title) { | ||
title = @""; | ||
} | ||
if (!block) { | ||
block = (^{}); | ||
} | ||
NSDictionary *buttonDetails = @{ | ||
kButtonTitle : title, | ||
kActionType : @(Block), | ||
kButtonValue : [block copy] | ||
}; | ||
[self.customButtons addObject:buttonDetails]; | ||
} | ||
|
||
- (void)addCustomButtonWithTitle:(NSString *)title target:(id)target selector:(SEL)selector | ||
{ | ||
if (!title) { | ||
title = @""; | ||
} | ||
if (!target) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The brackets here (in one-line expressions) is redundant. (not a mistake, just about code-style) |
||
target = [NSNull null]; | ||
} | ||
NSDictionary *buttonDetails = @{ | ||
kButtonTitle : title, | ||
kActionType : @(Selector), | ||
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"); | ||
selector(selectRow:inComponent:animated:)], @"customButtonPressed not overridden, cannot interact with subclassed pickerView"); | ||
|
||
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); | ||
|
||
NSInteger actionType = [buttonDetails[kActionType] intValue]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To clarify, what is |
||
switch (actionType) { | ||
case Value: { | ||
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); | ||
} | ||
break; | ||
} | ||
|
||
case Block: { | ||
ActionBlock actionBlock = buttonDetails[kButtonValue]; | ||
if (actionBlock) { actionBlock(); } | ||
break; | ||
} | ||
|
||
case Selector: { | ||
SEL selector = [buttonDetails[kButtonValue] pointerValue]; | ||
id target = buttonDetails[kActionTarget]; | ||
if (target && [target respondsToSelector:selector]) { | ||
SuppressPerformSelectorLeakWarning ( | ||
[target performSelector:selector]; | ||
); | ||
} | ||
break; | ||
} | ||
|
||
default: | ||
NSAssert(false, @"Unknown action type"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
break; | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -177,11 +177,41 @@ - (void)customButtonPressed:(id)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"); | ||
|
||
NSInteger actionType = [buttonDetails[kActionType] intValue]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. again: cast to |
||
switch (actionType) { | ||
case Value: { | ||
NSDate *itemValue = buttonDetails[kButtonValue]; | ||
UIDatePicker *picker = (UIDatePicker *)self.pickerView; | ||
[picker setDate:itemValue animated:YES]; | ||
[self eventForDatePicker:picker]; | ||
break; | ||
} | ||
|
||
case Block: { | ||
ActionBlock actionBlock = buttonDetails[kButtonValue]; | ||
if (actionBlock) { actionBlock(); } | ||
break; | ||
} | ||
|
||
case Selector: { | ||
SEL selector = [buttonDetails[kButtonValue] pointerValue]; | ||
id target = buttonDetails[kActionTarget]; | ||
if (target && [target respondsToSelector:selector]) { | ||
SuppressPerformSelectorLeakWarning ( | ||
[target performSelector:selector]; | ||
); | ||
} | ||
break; | ||
} | ||
|
||
default: | ||
NSAssert(false, @"Unknown action type"); | ||
break; | ||
} | ||
} | ||
|
||
@end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -367,14 +367,44 @@ - (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"); | ||
|
||
NSInteger actionType = [buttonDetails[kActionType] intValue]; | ||
switch (actionType) { | ||
case Value: { | ||
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 Block: { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try to avoid duplication of code as much as possible. |
||
ActionBlock actionBlock = buttonDetails[kButtonValue]; | ||
if (actionBlock) { actionBlock(); } | ||
break; | ||
} | ||
|
||
case Selector: { | ||
SEL selector = [buttonDetails[kButtonValue] pointerValue]; | ||
id target = buttonDetails[kActionTarget]; | ||
if (target && [target respondsToSelector:selector]) { | ||
SuppressPerformSelectorLeakWarning ( | ||
[target performSelector:selector]; | ||
); | ||
} | ||
break; | ||
} | ||
|
||
default: | ||
NSAssert(false, @"Unknown action type"); | ||
break; | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO: When people want to set custom action for button - explicit behaviour to hide picker automatically after button pressed. And it also simplify usage of picker custom buttons.
So, it's better to move
hidePickerWithCancelAction
inside of Picker logic and just dismiss picker and not call cancel action in this case.Moreover, it's preferrable to call actionBlock only after picker already dismissed to avoid bugs, such #63 (when you want to show another picker immediately after first one is dismissed.
I'm ready to discuss it in details.