Last active
October 3, 2015 08:48
-
-
Save advantis/2428642 to your computer and use it in GitHub Desktop.
UIActionSheet subclass that brings simple block API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Copyright © 2011 Yuri Kotov | |
// | |
#import <UIKit/UIKit.h> | |
typedef void(^ADVSheetAction) (); | |
@interface ADVActionSheet : UIActionSheet <UIActionSheetDelegate> | |
- (NSInteger) addButtonWithTitle:(NSString *)title action:(ADVSheetAction)action; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Copyright © 2011 Yuri Kotov | |
// | |
#import "ADVActionSheet.h" | |
#import <objc/runtime.h> | |
static inline BOOL ProtocolContainsSelector (Protocol *protocol, SEL selector) | |
{ | |
return NULL != protocol_getMethodDescription(protocol, selector, NO, YES).name; | |
} | |
@interface ADVActionSheet () | |
@property (nonatomic, strong) NSMutableArray *actions; | |
@property (nonatomic, weak) id<UIActionSheetDelegate> trueDelegate; | |
@end | |
@implementation ADVActionSheet | |
#pragma mark - ADVActionSheet | |
- (NSInteger) addButtonWithTitle:(NSString *)title action:(ADVSheetAction)action | |
{ | |
NSInteger index = [super addButtonWithTitle:title]; | |
self.actions[index] = action ?: (ADVSheetAction)^{}; | |
return index; | |
} | |
/** | |
* UIActionSheet performs a series of "respondsToSelector" calls on delegate change | |
* to determine which of the optional protocol methods it implements and cache | |
* this info. Therefore we need to force it to update this info for a new delegate. | |
*/ | |
- (void) refreshSupportedOptionalMethods | |
{ | |
super.delegate = nil; | |
super.delegate = self; | |
} | |
#pragma mark - UIActionSheet | |
- (id<UIActionSheetDelegate>) delegate | |
{ | |
return self.trueDelegate; | |
} | |
- (void) setDelegate:(id<UIActionSheetDelegate>)delegate | |
{ | |
if (delegate != self.trueDelegate && delegate != self) | |
{ | |
self.trueDelegate = delegate; | |
[self refreshSupportedOptionalMethods]; | |
} | |
} | |
- (NSInteger) addButtonWithTitle:(NSString *)title | |
{ | |
return [self addButtonWithTitle:title action:nil]; | |
} | |
#pragma mark - NSObject | |
- (id) init | |
{ | |
self = [super init]; | |
if (self) | |
{ | |
_actions = [[NSMutableArray alloc] initWithCapacity:4]; | |
super.delegate = self; | |
} | |
return self; | |
} | |
- (BOOL) respondsToSelector:(SEL)selector | |
{ | |
BOOL responds = [super respondsToSelector:selector]; | |
if (!responds && ProtocolContainsSelector(@protocol(UIActionSheetDelegate), selector)) | |
{ | |
responds = [self.trueDelegate respondsToSelector:selector]; | |
} | |
return responds; | |
} | |
- (id) forwardingTargetForSelector:(SEL)selector | |
{ | |
return ProtocolContainsSelector(@protocol(UIActionSheetDelegate), selector) | |
? self.trueDelegate | |
: [super forwardingTargetForSelector:selector]; | |
} | |
#pragma mark - UIActionSheetDelegate | |
- (void) actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex | |
{ | |
if ([self.trueDelegate respondsToSelector:_cmd]) | |
{ | |
[self.trueDelegate actionSheet:actionSheet clickedButtonAtIndex:buttonIndex]; | |
} | |
// Check for the case of tapping outside an action sheet on iPad | |
// Kudos to @parfeon for pointing this out | |
if (buttonIndex < [self.actions count]) | |
{ | |
((ADVSheetAction)self.actions[buttonIndex])(); | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment