IOS UIKIT framework的UIActionsheet是不支持block方式的,为什么我们需要block支持呢?
原因有
1. block的代码更灵活,而同一个NSObject派生对象里,通常只出现一个UIActionsheet delegate实现,出现多个情况变得复杂,需要if else判断,并且需要property 来保存 UIActionsheet以便在delegate回调中加以判断。
2.更麻烦的情况是,在有参数需要传递到delegate回调中时,更麻烦,代码将更乱。
解决方法,便是引入block
client调用的例子
[sheet showInView:view
handler:^(UIActionSheet *actionSheet, NSInteger buttonIndex) {
if (buttonIndex == [actionSheet cancelButtonIndex]) {
NSLog(@"Cancel button index tapped");
} else if (buttonIndex == [actionSheet destructiveButtonIndex]) {
NSLog(@"Destructive button index tapped");
} else {
NSLog(@"Button %i tapped", buttonIndex);
}
}];
源代码如下
#import "UIActionSheet+Blocks.h"#import <objc/runtime.h>/** Runtime association key.*/static NSString * kHandlerAssociatedKey = @"kHandlerAssociatedKey" ;@implementation UIActionSheet (Blocks)#pragma mark - Showing/** Shows the sheet from a view.*/- ( void ) showInView: ( UIView * ) view handler: ( UIActionSheetHandler ) handler {objc_setAssociatedObject ( self , ( __bridge const void * )( kHandlerAssociatedKey ), handler , OBJC_ASSOCIATION_RETAIN_NONATOMIC );[ self setDelegate: self ];[ self showInView: view ];}/** Shows the sheet from a bar button item.*/- ( void ) showFromBarButtonItem: ( UIBarButtonItem * ) item animated: ( BOOL ) animated handler: ( UIActionSheetHandler ) handler {objc_setAssociatedObject ( self , ( __bridge const void * )( kHandlerAssociatedKey ), handler , OBJC_ASSOCIATION_RETAIN_NONATOMIC );[ self setDelegate: self ];[ self showFromBarButtonItem: item animated: animated ];}/** Shows the sheet from a rect.*/- ( void ) showFromRect: ( CGRect ) rect inView: ( UIView * ) view animated: ( BOOL ) animated handler: ( UIActionSheetHandler ) handler {objc_setAssociatedObject ( self , ( __bridge const void * )( kHandlerAssociatedKey ), handler , OBJC_ASSOCIATION_RETAIN_NONATOMIC );[ self setDelegate: self ];[ self showFromRect: rect inView: view animated: animated ];}/** Shows the sheet from a tab bar.*/- ( void ) showFromTabBar: ( UITabBar * ) view handler: ( UIActionSheetHandler ) handler {objc_setAssociatedObject ( self , ( __bridge const void * )( kHandlerAssociatedKey ), handler , OBJC_ASSOCIATION_RETAIN_NONATOMIC );[ self setDelegate: self ];[ self showFromTabBar: view ];}/** Shows the sheet from a toobar.*/- ( void ) showFromToolbar: ( UIToolbar * ) view handler: ( UIActionSheetHandler ) handler {objc_setAssociatedObject ( self , ( __bridge const void * )( kHandlerAssociatedKey ), handler , OBJC_ASSOCIATION_RETAIN_NONATOMIC );[ self setDelegate: self ];[ self showFromToolbar: view ];}#pragma mark - UIActionSheetDelegate/** Sent to the delegate when the user clicks a button on an action sheet.*/- ( void ) actionSheet: ( UIActionSheet * ) actionSheet clickedButtonAtIndex: ( NSInteger ) buttonIndex {UIActionSheetHandler completionHandler = objc_getAssociatedObject ( self , ( __bridge const void * )( kHandlerAssociatedKey ));if ( completionHandler != nil ) {completionHandler ( actionSheet , buttonIndex );}}@end
实现分析
/** Shows the sheet from a bar button item.*/- ( void ) showFromBarButtonItem: ( UIBarButtonItem * ) item animated: ( BOOL ) animated handler: ( UIActionSheetHandler ) handler {objc_setAssociatedObject ( self , ( __bridge const void * )( kHandlerAssociatedKey ), handler , OBJC_ASSOCIATION_RETAIN_NONATOMIC );[ self setDelegate: self ];[ self showFromBarButtonItem: item animated: animated ];}
1.代码以category方式实现,更加方便的引入到我们的工程中,成本低,不引入新的class
2.通过objc_setAssociatedObject runtime函数,像class中加入handler property,以便在delegate里加调该block
#pragma mark - UIActionSheetDelegate/** Sent to the delegate when the user clicks a button on an action sheet.*/- ( void ) actionSheet: ( UIActionSheet * ) actionSheet clickedButtonAtIndex: ( NSInteger ) buttonIndex {UIActionSheetHandler completionHandler = objc_getAssociatedObject ( self , ( __bridge const void * )( kHandlerAssociatedKey ));if ( completionHandler != nil ) {completionHandler ( actionSheet , buttonIndex );}}
3.在category中实现了delegate回调方法,并调用了该block handler.
https://github.com/emenegro/action-sheet-blocks