I'm trying to write a helper class to allow our app to support both UIAlertAction
and UIAlertView
. However, when writing the alertView:clickedButtonAtIndex:
method for the UIAlertViewDelegate
, I came across this issue: I see no way to execute the code in the handler block of a UIAlertAction
.
I'm trying to do this by keeping an array of UIAlertAction
s in a property called handlers
@property (nonatomic, strong) NSArray *handlers;
and then implement a delegate like such:
- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
UIAlertAction *action = self.handlers[buttonIndex];
if (action.enabled)
action.handler(action);
}
However, there is no action.handler
property, or indeed any way I can see to fetch that, since the UIAlertAction
header just has:
NS_CLASS_AVAILABLE_IOS(8_0) @interface UIAlertAction : NSObject <NSCopying>
+ (instancetype)actionWithTitle:(NSString *)title style:(UIAlertActionStyle)style handler:(void (^)(UIAlertAction *action))handler;
@property (nonatomic, readonly) NSString *title;
@property (nonatomic, readonly) UIAlertActionStyle style;
@property (nonatomic, getter=isEnabled) BOOL enabled;
@end
Is there some other way to execute the code in the handler
block of a UIAlertAction
?
After some experimentation I just figured this out. Turns out that the handler block can be cast as a function pointer, and the function pointer can be executed.
Like so
//Get the UIAlertAction
UIAlertAction *action = self.handlers[buttonIndex];
//Cast the handler block into a form that we can execute
void (^someBlock)(id obj) = [action valueForKey:@"handler"];
//Execute the block
someBlock(action);
Wrapper classes are great, eh?
In the .h
:
@interface UIAlertActionWrapper : NSObject
@property (nonatomic, strong) void (^handler)(UIAlertAction *);
@property (nonatomic, strong) NSString *title;
@property (nonatomic, assign) UIAlertActionStyle style;
@property (nonatomic, assign) BOOL enabled;
- (id) initWithTitle: (NSString *)title style: (UIAlertActionStyle)style handler: (void (^)(UIAlertAction *))handler;
- (UIAlertAction *) toAlertAction;
@end
and in the .m
:
- (UIAlertAction *) toAlertAction
{
UIAlertAction *action = [UIAlertAction actionWithTitle:self.title style:self.style handler:self.handler];
action.enabled = self.enabled;
return action;
}
...
- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
UIAlertActionWrapper *action = self.helpers[buttonIndex];
if (action.enabled)
action.handler(action.toAlertAction);
}
All you have to do is make sure UIAlertActionWrapper
s are inserted into helpers
instead of UIAlertAction
s.
This way, you can make all properties gettable and settable to your heart's content, and still retain the functionality provided by the original class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With