簡(jiǎn)單的封裝UIAlertView、UIActionSheet染突、UIAlertController捻爷、KVO粘姜。封裝之后不使用代理己莺,使用block直接調(diào)用響應(yīng)事件劳坑。
直接提供Demo地址:SimpleBlock
1崭添、UIAlertView 封裝
1货矮、 靜態(tài)方法Block實(shí)現(xiàn)。
typedef void (^ClickAtIndexBlock)(NSInteger buttonIndex);
@interface KAlertView : NSObject <UIAlertViewDelegate>
+ (UIAlertView *)initWithTitle:(NSString *)title
message:(NSString *)messge
cancleButtonTitle:(NSString *)cancleButtonTitle
OtherButtonsArray:(NSArray *)otherButtons
clickAtIndex:(ClickAtIndexBlock)clickAtIndex;
@end
初始化方法薪贫,加一個(gè)Block艘狭。
static ClickAtIndexBlock _ClickAtIndexBlock;
@implementation KAlertView
+ (UIAlertView *)initWithTitle:(NSString *)title
message:(NSString *)messge
cancleButtonTitle:(NSString *)cancleButtonTitle
OtherButtonsArray:(NSArray *)otherButtons
clickAtIndex:(ClickAtIndexBlock)clickAtIndex {
_ClickAtIndexBlock = [clickAtIndex copy];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:title
message:messge
delegate:self
cancelButtonTitle:cancleButtonTitle
otherButtonTitles: nil];
for (NSString *otherTitle in otherButtons) {
[alertView addButtonWithTitle:otherTitle];
}
[alertView show];
return alertView;
}
#pragma mark UIAlertViewDelegate
+ (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
_ClickAtIndexBlock(buttonIndex);
}
+ (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
_ClickAtIndexBlock = nil;
}
@end
注解:
我們這里的UIAlertView代理不是給的類(lèi)對(duì)象,而是給的類(lèi)本身囚霸,而類(lèi)本身也是對(duì)象腰根,是元類(lèi)的對(duì)象,所以代理方法也要改成類(lèi)本身的代理方法拓型,方能執(zhí)行额嘿。
UIAlertView的封裝就完成了,調(diào)用的時(shí)候我們就可以相對(duì)簡(jiǎn)單一點(diǎn)了劣挫。
[KAlertView initWithTitle:@"title" message:@"message" cancleButtonTitle:@"cancle" OtherButtonsArray:@[@"sure",@"very"] clickAtIndex:^(NSInteger buttonIndex) {
NSLog(@"--index : %ld",buttonIndex);
}];
1册养、 Runtime Block實(shí)現(xiàn)。
@interface KRAlertView : NSObject <UIAlertViewDelegate>
typedef void (^ClickAtIndexBlock)(NSInteger buttonIndex);
+ (UIAlertView *)initWithTitle:(NSString*)title
message:(NSString *)messge
cancleButtonTitle:(NSString *)cancleButtonTitle
OtherButtonsArray:(NSArray*)otherButtons
clickAtIndex:(ClickAtIndexBlock) clickAtIndex;
@end
和第一個(gè)實(shí)現(xiàn)方法一樣压固,加一個(gè)block 一個(gè)初始化
#import <objc/runtime.h>
const char *KUIAlertView_runtime_key = "KUIAlertView_runtime_key";
@interface UIAlertView (KRAlertView)
- (void)setClickBlock:(ClickAtIndexBlock)block;
- (ClickAtIndexBlock)clickBlock;
@end
@implementation UIAlertView(KRAlertView)
- (void)setClickBlock:(ClickAtIndexBlock)block {
objc_setAssociatedObject(self, KUIAlertView_runtime_key, block, OBJC_ASSOCIATION_COPY);
}
- (ClickAtIndexBlock)clickBlock {
return objc_getAssociatedObject(self, KUIAlertView_runtime_key);
}
@end
@implementation KRAlertView
+ (UIAlertView *)initWithTitle:(NSString*)title
message:(NSString *)messge
cancleButtonTitle:(NSString *)cancleButtonTitle
OtherButtonsArray:(NSArray*)otherButtons
clickAtIndex:(ClickAtIndexBlock) clickAtIndex {
UIAlertView *alerView = [[UIAlertView alloc] initWithTitle:title message:messge delegate:self cancelButtonTitle:cancleButtonTitle otherButtonTitles: nil];
alerView.clickBlock = clickAtIndex;
for (NSString *otherTitle in otherButtons) {
[alerView addButtonWithTitle:otherTitle];
}
[alerView show];
return alerView;
}
#pragma mark UIAlertViewDelegate
+ (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (alertView.clickBlock) {
alertView.clickBlock(buttonIndex);
}
}
實(shí)際上runtime實(shí)現(xiàn)的主要思想就是給UIAlertView的類(lèi)別加一個(gè)block屬性球拦。然后就可以直接使用這個(gè)屬性,從而調(diào)用block邓夕。
這里面的主要思想是runtime的關(guān)聯(lián)屬性
objc_setAssociatedObject(self, KUIAlertView_runtime_key, block, OBJC_ASSOCIATION_COPY);
將某個(gè)值跟某個(gè)對(duì)象關(guān)聯(lián)起來(lái)刘莹,將某個(gè)值存儲(chǔ)到某個(gè)對(duì)象中
// 第一個(gè)參數(shù):給哪個(gè)對(duì)象添加屬性
// 第二個(gè)參數(shù):屬性名稱(chēng)
// 第三個(gè)參數(shù):屬性值
// 第四個(gè)參數(shù):保存策略
objc_getAssociatedObject(self, KUIAlertView_runtime_key);
獲取相應(yīng)對(duì)象的關(guān)聯(lián)值。
調(diào)用和第一種方法相同焚刚。
2点弯、UIActionSheet 封裝
UIActionSheet 實(shí)現(xiàn)方法和UIAlertView相同,但是這里提供一個(gè)不需要靜態(tài)方法矿咕,使用runtime的實(shí)現(xiàn)方式抢肛。首先創(chuàng)建一個(gè)類(lèi)別,具體代碼如下碳柱。
typedef void (^ClickAtIndexBlock)(NSInteger buttonIndex);
@interface UIActionSheet (block)
- (void)showActionSheetInView:(UIView *)showView clickCompleteBlock:(ClickAtIndexBlock)block;
@end
#import <objc/runtime.h>
static void *key = "KActionSheet_runtime_key";
@implementation UIActionSheet (block)
- (void)showActionSheetInView:(UIView *)showView clickCompleteBlock:(ClickAtIndexBlock)block {
if (block) {
objc_removeAssociatedObjects(self);
objc_setAssociatedObject(self, key, block, OBJC_ASSOCIATION_COPY);
self.delegate = (id<UIActionSheetDelegate>)self;
}
[self showInView:showView];
}
#pragma mark UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
ClickAtIndexBlock block = objc_getAssociatedObject(self, key);
if (block) {
block(buttonIndex);
}
}
@end
原理類(lèi)似捡絮,只是這種方法調(diào)用相對(duì)其他兩種方法多一句話(huà)如下
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:@"title" delegate:nil cancelButtonTitle:@"cancel" destructiveButtonTitle:nil otherButtonTitles:@"1",@"2", nil];
[actionSheet showActionSheetInView:self.view clickCompleteBlock:^(NSInteger buttonIndex) {
NSLog(@"--- %ld",buttonIndex);
}];
3、UIAlertController 封裝
ios8之后不是推薦使用這個(gè)控件嗎莲镣,當(dāng)然這個(gè)功能相對(duì)比UIAlertView和UIActionSheet要強(qiáng)大福稳,所以我也就稍微封裝一下。這個(gè)封裝就沒(méi)有runtime瑞侮,也沒(méi)有使用類(lèi)對(duì)象了的圆,直接上代碼。
#import <UIKit/UIKit.h>
typedef void (^ClickAlertBlock)(NSString *title);
@interface KAlertController : NSObject
+ (UIAlertController *)showAlertWith:(UIViewController *)showController
title:(NSString *)title
message:(NSString *)message
cancleTitle:(NSString *)cancleTitle
actionTitle:(NSArray *)titleArrary
alertType:(UIAlertControllerStyle)alerType
andClickAlertBlock:(ClickAlertBlock)block;
@end
@implementation KAlertController
+ (UIAlertController *)showAlertWith:(UIViewController *)showController
title:(NSString *)title
message:(NSString *)message
cancleTitle:(NSString *)cancleTitle
actionTitle:(NSArray *)titleArrary
alertType:(UIAlertControllerStyle)alerType
andClickAlertBlock:(ClickAlertBlock)block {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:alerType];
for (NSString *actionTitle in titleArrary) {
UIAlertAction *action = [UIAlertAction actionWithTitle:actionTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (block) {
block(actionTitle);
}
}];
[alertController addAction:action];
}
UIAlertAction *action = [UIAlertAction actionWithTitle:cancleTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
if (block) {
block(cancleTitle);
}
}];
[alertController addAction:action];
[showController presentViewController:alertController animated:YES completion:nil];
return alertController;
}
@end
調(diào)用也是一句話(huà)半火,根據(jù)枚舉調(diào)用出來(lái)你想要的越妈,這里只舉例UIAlertVIew
[KAlertController showAlertWith:self
title:@"title"
message:@"message"
cancleTitle:@"cancle"
actionTitle:@[@"1",@"2"]
alertType:UIAlertControllerStyleAlert
andClickAlertBlock:^(NSString *title) {
NSLog(@"title :%@",title);
}];
4、KVO Block調(diào)用
原理和以上類(lèi)似钮糖,只需要加一個(gè)NSObject類(lèi)別
typedef void (^CompleteChangeBlock)(id _Nonnull obj, id _Nonnull oldVal, id _Nonnull newVal);
@interface NSObject (KVO)
- (void)addObserver:(NSObject *_Nullable)observer
forKeyPath:(NSString *_Nullable)keyPath
completeChangeBlock:(CompleteChangeBlock _Nullable )block;
@end
static CompleteChangeBlock _CompleteChangeBlock;
@implementation NSObject (KVO)
- (void)addObserver:(NSObject *_Nullable)observer
forKeyPath:(NSString *_Nullable)keyPath
completeChangeBlock:(CompleteChangeBlock _Nullable )block {
_CompleteChangeBlock = block;
[self addObserver:observer forKeyPath:keyPath options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)contextt {
if (_CompleteChangeBlock) {
_CompleteChangeBlock(object,change[@"old"],change[@"new"]);
}
}
@end
調(diào)用:
[self addObserver:self forKeyPath:@"number" completeChangeBlock:^(id _Nonnull obj, id _Nonnull oldVal, id _Nonnull newVal) {
NSLog(@"obj :%@ old: %@ new: %@",obj,oldVal,newVal);
}];