前言:众所周知,现在的UIAlertView和UISheetView合并组成了UIAlertController。前几天用到了UIAlertController的UIAlertControllerStyleActionSheet类型,才发现如果要展示多条数据的话,要写好长代码,并且每个Action的block内部都要做响应的操作的话就会让代码看起来非常的繁琐且凌乱。在此前提下,小编想到了封装,如果我自己封装一个SheetView,能够用起来不这么繁琐就好了。
原理:只需要创建的时候传入title和message,然后设置一下Action的title,采用代理的方式传入Action的类型,并将Action的事件使用代理传递。
下面给大家详细介绍:
首先,我是创建了一个类继承于NSObject,由于方法参数使用到了UI控件,所以要导入UIKit框架。在.h文件中设置代理协议及方法,并声明相关参数和接口方法。代码如下:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@protocol RHSheetViewDelegate;
@interface RHSheetView : NSObject
//声明代理
@property (nonatomic, weak) id<RHSheetViewDelegate> delegate;
//Action的title数组
@property (nonatomic, strong) NSArray * actionTitles;
//自定义构造方法
- (instancetype)initWithTitle:(NSString *)title message:(NSString *)message;
//跳转展示方法
- (void)showWithController:(UIViewController *)controller;
@end
//设置代理协议及方法
@protocol RHSheetViewDelegate <NSObject>
@optional //非必须实现代理方法
//返回Action的样式
- (UIAlertActionStyle)sheetView:(RHSheetView *)sheetView actionStyleAtIndex:(NSInteger)index;
//点击相应的Action之后触发的方法
- (void)sheetView:(RHSheetView *)sheetView didSelectedAtIndex:(NSInteger)index;
@end
然后,在.m文件中声明一个私有的UIAlertController全局对象,实现.h中声明相应的方法及属性的setter方法。代码如下:
#import "RHSheetView.h"
@interface RHSheetView ()
//声明UIAlertController对象
@property (nonatomic, strong) UIAlertController * alert;
@end
@implementation RHSheetView
#pragma mark - public
- (instancetype)initWithTitle:(NSString *)title message:(NSString *)message {
self = [super init];
if (self) {
//构造方法中创建声明的对象
_alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleActionSheet];
}
return self;
}
- (void)showWithController:(UIViewController *)controller {
//在相应的Controller中弹出弹窗
[controller presentViewController:_alert animated:YES completion:nil];
}
#pragma mark - setter
//重写声明的数组属性的setter方法
- (void)setActionTitles:(NSArray *)actionTitles {
//对属性赋值
_actionTitles = actionTitles;
//for循环创建Action
for (int i = 0; i < actionTitles.count; i++) {
//如果通过代理返回了Action的样式,则根据返回的样式设置相应Action的样式
if ([self.delegate respondsToSelector:@selector(sheetView:actionStyleAtIndex:)]) {
UIAlertActionStyle style = [self.delegate sheetView:self actionStyleAtIndex:i];
UIAlertAction * action = [UIAlertAction actionWithTitle:actionTitles[i] style:style handler:^(UIAlertAction * _Nonnull action) {
//在此设置Action的点击代理方法
if ([self.delegate respondsToSelector:@selector(sheetView:didSelectedAtIndex:)]) {
[self.delegate sheetView:self didSelectedAtIndex:i];
}
//点击之后返回到当前界面
[_alert dismissViewControllerAnimated:YES completion:nil];
}];
[_alert addAction:action];
}else {
//如果没有返回Action样式,则默认设置为UIAlertActionStyleDefault
UIAlertAction * action = [UIAlertAction actionWithTitle:actionTitles[i] style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//在此设置Action的点击代理方法
if ([self.delegate respondsToSelector:@selector(sheetView:didSelectedAtIndex:)]) {
[self.delegate sheetView:self didSelectedAtIndex:i];
}
//点击之后返回到当前界面
[_alert dismissViewControllerAnimated:YES completion:nil];
}];
[_alert addAction:action];
}
}
}
OK!到此封装就结束了,接下来就是实际应用了。在应用中无论需要添加多少个Action,我们要写的代码长度都差不多,小编举了个例子具体如下:
#import "ViewController.h"
#import "RHSheetView.h"
@interface ViewController () <RHSheetViewDelegate>
@property (nonatomic, strong) UIButton * btn;
@property (nonatomic, strong) RHSheetView * sheet;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
[self test];
}
//测试创建了一个button
- (void)test {
_btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 150, 50)];
_btn.center = self.view.center;
_btn.backgroundColor = [UIColor lightGrayColor];
[_btn setTitle:@"选择更改" forState:UIControlStateNormal];
[_btn addTarget:self action:@selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_btn];
}
- (void)btnClick:(UIButton *)btn {
//button点击弹出SheetView
[self.sheet showWithController:self];
}
//懒加载创建(这个是小编习惯的创建方式)
- (RHSheetView *)sheet {
if (!_sheet) {
_sheet = [[RHSheetView alloc] initWithTitle:@"请选择支付方式" message:@""];
_sheet.delegate = self;
_sheet.actionTitles = @[@"支付宝支付", @"微信支付", @"取消"];
}
return _sheet;
}
#pragma mark - 代理方法实现
//返回Action的样式
- (UIAlertActionStyle)sheetView:(RHSheetView *)sheetView actionStyleAtIndex:(NSInteger)index {
if (index == 0) {
return UIAlertActionStyleDestructive;
}else if (index == sheetView.actionTitles.count - 1) {
return UIAlertActionStyleCancel;
}
return UIAlertActionStyleDefault;
}
//Action点击触发的事件
- (void)sheetView:(RHSheetView *)sheetView didSelectedAtIndex:(NSInteger)index {
if (index < sheetView.actionTitles.count - 1) {
[_btn setTitle:sheetView.actionTitles[index] forState:UIControlStateNormal];
}
}
@end
在此小编截图了几张给大家看看效果
如果还有什么不清晰的地方,小编做了Demo已上传到GitHub上边,大家可以去下载看看,git下载地址:https://github.com/guorenhao/SheetView.git
最后,还是希望能够帮到有需要的朋友们,愿同是程序猿的我们能够共同学习进步,在开发的道路上越走越远!谢谢!