/BlocksKit/UIAlertView+BlocksKit.m

http://github.com/zwaldowski/BlocksKit · Objective C · 214 lines · 155 code · 50 blank · 9 comment · 32 complexity · 04f86a0975456e0a77133e7d0497714c MD5 · raw file

  1. //
  2. // UIAlertView+BlocksKit.m
  3. // BlocksKit
  4. //
  5. #import "NSArray+BlocksKit.h"
  6. #import "UIAlertView+BlocksKit.h"
  7. #import "A2BlockDelegate+BlocksKit.h"
  8. #pragma mark Delegate
  9. @interface A2DynamicUIAlertViewDelegate : A2DynamicDelegate <UIAlertViewDelegate>
  10. @end
  11. @implementation A2DynamicUIAlertViewDelegate
  12. - (BOOL)alertViewShouldEnableFirstOtherButton:(UIAlertView *)alertView {
  13. BOOL should = YES;
  14. id realDelegate = self.realDelegate;
  15. if (realDelegate && [realDelegate respondsToSelector:@selector(alertViewShouldEnableFirstOtherButton:)])
  16. should &= [realDelegate alertViewShouldEnableFirstOtherButton:alertView];
  17. BOOL (^block)(UIAlertView *) = [self blockImplementationForMethod:_cmd];
  18. if (block)
  19. should &= block(alertView);
  20. return should;
  21. }
  22. - (void)alertViewCancel:(UIAlertView *)alertView {
  23. id realDelegate = self.realDelegate;
  24. if (realDelegate && [realDelegate respondsToSelector:@selector(alertViewCancel:)])
  25. [realDelegate alertViewCancel:alertView];
  26. id key = [NSNumber numberWithInteger:alertView.cancelButtonIndex];
  27. BKBlock cancelBlock = [self.handlers objectForKey:key];
  28. if (cancelBlock)
  29. cancelBlock();
  30. }
  31. - (void)willPresentAlertView:(UIAlertView *)alertView {
  32. id realDelegate = self.realDelegate;
  33. if (realDelegate && [realDelegate respondsToSelector:@selector(willPresentAlertView:)])
  34. [realDelegate willPresentAlertView:alertView];
  35. void (^block)(UIAlertView *) = [self blockImplementationForMethod:_cmd];
  36. if (block)
  37. block(alertView);
  38. }
  39. - (void)didPresentAlertView:(UIAlertView *)alertView {
  40. id realDelegate = self.realDelegate;
  41. if (realDelegate && [realDelegate respondsToSelector:@selector(didPresentAlertView:)])
  42. [realDelegate didPresentAlertView:alertView];
  43. void (^block)(UIAlertView *) = [self blockImplementationForMethod:_cmd];
  44. if (block)
  45. block(alertView);
  46. }
  47. - (void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex {
  48. id realDelegate = self.realDelegate;
  49. if (realDelegate && [realDelegate respondsToSelector:@selector(alertView:willDismissWithButtonIndex:)])
  50. [realDelegate alertView:alertView willDismissWithButtonIndex:buttonIndex];
  51. void (^block)(UIAlertView *, NSInteger) = [self blockImplementationForMethod:_cmd];
  52. if (block)
  53. block(alertView, buttonIndex);
  54. }
  55. - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
  56. id realDelegate = self.realDelegate;
  57. if (realDelegate && [realDelegate respondsToSelector:@selector(alertView:didDismissWithButtonIndex:)])
  58. [realDelegate alertView:alertView didDismissWithButtonIndex:buttonIndex];
  59. void (^block)(UIAlertView *, NSInteger) = [self blockImplementationForMethod:_cmd];
  60. if (block)
  61. block(alertView, buttonIndex);
  62. }
  63. - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
  64. id realDelegate = self.realDelegate;
  65. if (realDelegate && [realDelegate respondsToSelector:@selector(alertView:clickedButtonAtIndex:)])
  66. [realDelegate alertView:alertView clickedButtonAtIndex:buttonIndex];
  67. void (^block)(UIAlertView *, NSInteger) = [self blockImplementationForMethod:_cmd];
  68. if (block)
  69. block(alertView, buttonIndex);
  70. id key = [NSNumber numberWithInteger:buttonIndex];
  71. BKBlock buttonBlock = [self.handlers objectForKey: key];
  72. if (buttonBlock)
  73. buttonBlock();
  74. }
  75. @end
  76. #pragma mark - Category
  77. @implementation UIAlertView (BlocksKit)
  78. @dynamic willShowBlock, didShowBlock, willDismissBlock, didDismissBlock, shouldEnableFirstOtherButtonBlock;
  79. + (void)load {
  80. @autoreleasepool {
  81. [self registerDynamicDelegate];
  82. NSDictionary *methods = [NSDictionary dictionaryWithObjectsAndKeys:
  83. @"willPresentAlertView:", @"willShowBlock",
  84. @"didPresentAlertView:", @"didShowBlock",
  85. @"alertView:willDismissWithButtonIndex:", @"willDismissBlock",
  86. @"alertView:didDismissWithButtonIndex:", @"didDismissBlock",
  87. @"alertViewShouldEnableFirstOtherButton:", @"shouldEnableFirstOtherButtonBlock",
  88. nil];
  89. [self linkDelegateMethods:methods];
  90. }
  91. }
  92. #pragma mark Convenience
  93. + (void) showAlertViewWithTitle: (NSString *) title message: (NSString *) message cancelButtonTitle: (NSString *) cancelButtonTitle otherButtonTitles: (NSArray *) otherButtonTitles handler: (void (^)(UIAlertView *, NSInteger)) block
  94. {
  95. UIAlertView *alertView = [UIAlertView alertViewWithTitle: title message: message];
  96. // If no buttons were specified, cancel button becomes "Dismiss"
  97. if (!cancelButtonTitle.length && !otherButtonTitles.count)
  98. cancelButtonTitle = NSLocalizedString(@"Dismiss", nil);
  99. // Set cancel button
  100. if (cancelButtonTitle.length)
  101. alertView.cancelButtonIndex = [alertView addButtonWithTitle: cancelButtonTitle];
  102. // Set other buttons
  103. if (otherButtonTitles.count)
  104. {
  105. NSUInteger firstOtherButton = [alertView addButtonWithTitle: [otherButtonTitles objectAtIndex: 0]];
  106. [alertView setValue: [NSNumber numberWithInteger: firstOtherButton] forKey: @"firstOtherButton"];
  107. otherButtonTitles = [otherButtonTitles subarrayWithRange: NSMakeRange(1, otherButtonTitles.count - 1)];
  108. [otherButtonTitles each: ^(NSString *button) {
  109. [alertView addButtonWithTitle: button];
  110. }];
  111. }
  112. // Set `didDismissBlock`
  113. if (block) alertView.didDismissBlock = block;
  114. // Show alert view
  115. [alertView show];
  116. }
  117. #pragma mark Initializers
  118. + (id)alertViewWithTitle:(NSString *)title {
  119. return [self alertViewWithTitle:title message:nil];
  120. }
  121. + (id)alertViewWithTitle:(NSString *)title message:(NSString *)message {
  122. return [[[UIAlertView alloc] initWithTitle:title message:message] autorelease];
  123. }
  124. - (id)initWithTitle:(NSString *)title message:(NSString *)message {
  125. return [self initWithTitle:title message:message delegate:self.dynamicDelegate cancelButtonTitle:nil otherButtonTitles:nil];
  126. }
  127. #pragma Actions
  128. - (NSInteger)addButtonWithTitle:(NSString *)title handler:(BKBlock)block {
  129. NSAssert(title.length, @"A button without a title cannot be added to the alert view.");
  130. NSInteger index = [self addButtonWithTitle:title];
  131. [self setHandler:block forButtonAtIndex:index];
  132. return index;
  133. }
  134. - (NSInteger)setCancelButtonWithTitle:(NSString *)title handler:(BKBlock)block {
  135. if (!title.length)
  136. title = NSLocalizedString(@"Cancel", nil);
  137. NSInteger cancelButtonIndex = [self addButtonWithTitle:title];
  138. self.cancelButtonIndex = cancelButtonIndex;
  139. [self setHandler:block forButtonAtIndex:cancelButtonIndex];
  140. return cancelButtonIndex;
  141. }
  142. #pragma mark Properties
  143. - (void)setHandler:(BKBlock)block forButtonAtIndex:(NSInteger)index {
  144. id key = [NSNumber numberWithInteger:index];
  145. if (block)
  146. [[self.dynamicDelegate handlers] setObject:block forKey:key];
  147. else
  148. [[self.dynamicDelegate handlers] removeObjectForKey:key];
  149. }
  150. - (BKBlock)handlerForButtonAtIndex:(NSInteger)index {
  151. id key = [NSNumber numberWithInteger:index];
  152. return [[self.dynamicDelegate handlers] objectForKey:key];
  153. }
  154. - (BKBlock)cancelBlock {
  155. return [self handlerForButtonAtIndex:self.cancelButtonIndex];
  156. }
  157. - (void)setCancelBlock:(BKBlock)block {
  158. if (block && self.cancelButtonIndex == -1) {
  159. [self setCancelButtonWithTitle:nil handler:block];
  160. return;
  161. }
  162. [self setHandler:block forButtonAtIndex:self.cancelButtonIndex];
  163. }
  164. @end