public
Last active

UIActionSheet subclass that brings simple block API

  • Download Gist
ADVActionSheet.h
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14
//
// Copyright © 2011 Yuri Kotov
//
 
 
#import <UIKit/UIKit.h>
 
typedef void(^ADVSheetAction) ();
 
@interface ADVActionSheet : UIActionSheet <UIActionSheetDelegate>
 
- (NSInteger) addButtonWithTitle:(NSString *)title action:(ADVSheetAction)action;
 
@end
ADVActionSheet.m
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
//
// 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 the action sheet on iPad
// Kudos to @parfeon for pointing this out
if (buttonIndex < [self.actions count])
{
((ADVSheetAction)self.actions[buttonIndex])();
}
}
 
@end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.