前言
我們都知道UIAlertView UIActionSheet
是iOS 8.0之前的方法,在iOS 8.0之后,蘋果公司開始放棄這些方法,采用UIAlertController
來制作提醒提示框。
所以此次的目的主要是將UIAlertView UIActionSheet UIAlertController
統(tǒng)一封裝,根據(jù)用戶手機(jī)系統(tǒng)版本自動(dòng)采用UIAlertView UIActionSheet
還是 UIAlertController
。
這樣可以保證你的代碼可以跨系統(tǒng)使用。
具體效果如下:
未命名.gif
知識點(diǎn)一:NS_REQUIRES_NIL_TERMINATION
NS_REQUIRES_NIL_TERMINATION
是一個(gè)宏,告知編譯器 需要一個(gè)結(jié)尾的參數(shù),告知編譯器參數(shù)的列表已經(jīng)到最后一個(gè)不要再繼續(xù)執(zhí)行下去了。
該方法總傳遞的Action Item 和 數(shù)組之間的轉(zhuǎn)換為:
// 讀取可變參數(shù)里面的titles數(shù)組
NSMutableArray *titleArray = [[NSMutableArray alloc] initWithCapacity:0];
va_list list;
if(buttonTitles) {
//1.取得第一個(gè)參數(shù)的值(即是buttonTitles)
[titleArray addObject:buttonTitles];
//2.從第2個(gè)參數(shù)開始,依此取得所有參數(shù)的值
NSString *otherTitle;
va_start(list, buttonTitles);
while ((otherTitle= va_arg(list, NSString*))) {
[titleArray addObject:otherTitle];
}
va_end(list);
}
知識點(diǎn)二:UIAlertControllerStyleActionSheet
與UIActionSheet
區(qū)別
UIAlertControllerStyleActionSheet
支持message
;
而UIActionSheet
是沒有message
只有title
;
具體大家可以查看各自的初始化方法就知道了。
這里直接上代碼
.h文件
//
// LeeAlertSheetView.h
// FrameWork
//
// Created by LeeMiao on 2017/8/9.
// Copyright ? 2017年 Limiao. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef void(^myAlertSheetViewBlock)(NSInteger buttonTag,NSString *buttonTitle);
static NSInteger const cancelIndex = -1;
@interface LeeAlertSheetView : NSObject
/**
單例模式
@return 單例對象
*/
+(LeeAlertSheetView *)sharedInstacne;
/**
* 創(chuàng)建提示框(Alert 可變參數(shù)版)
*
* @param title 標(biāo)題
* @param message 提示內(nèi)容
* @param cancelTitle 取消按鈕(無操作,為nil則只顯示一個(gè)按鈕)
* @param vc VC iOS8及其以后會用到
* @param confirm 點(diǎn)擊按鈕的回調(diào)(取消按鈕的Index是cancelIndex -1)
* @param buttonTitles 按鈕(為nil,默認(rèn)為"確定",傳參數(shù)時(shí)必須以nil結(jié)尾,否則會崩潰)
*/
- (void)showAlert:(NSString *)title message:(NSString *)message cancelTitle:(NSString *)cancelTitle viewController:(UIViewController *)vc confirm:(myAlertSheetViewBlock)confirm buttonTitles:(NSString *)buttonTitles, ... NS_REQUIRES_NIL_TERMINATION;
/**
* 創(chuàng)建菜單(Sheet 可變參數(shù)版)
*
* @param title 標(biāo)題
* @param message 提示內(nèi)容
* @param cancelTitle 取消按鈕(無操作,為nil則只顯示一個(gè)按鈕)
* @param vc VC
* @param confirm 點(diǎn)擊按鈕的回調(diào)(取消按鈕的Index是cancelIndex -1)
* @param buttonTitles 按鈕(為nil,默認(rèn)為"確定",傳參數(shù)時(shí)必須以nil結(jié)尾,否則會崩潰)
*/
- (void)showSheet:(NSString *)title message:(NSString *)message cancelTitle:(NSString *)cancelTitle viewController:(UIViewController *)vc confirm:(myAlertSheetViewBlock)confirm buttonTitles:(NSString *)buttonTitles, ... NS_REQUIRES_NIL_TERMINATION ;
@end
.m文件
//
// LeeAlertSheetView.m
// FrameWork
//
// Created by LeeMiao on 2017/8/9.
// Copyright ? 2017年 Limiao. All rights reserved.
//
#import "LeeAlertSheetView.h"
#define RootVC [[UIApplication sharedApplication] keyWindow].rootViewController
#define IOS8AndLater [[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0
@interface LeeAlertSheetView () <UIActionSheetDelegate,UIAlertViewDelegate>
@property (nonatomic, copy) myAlertSheetViewBlock block;
@property (nonatomic,assign) NSInteger selectBtnTag;
@end
@implementation LeeAlertSheetView
#pragma mark- 對外方法
+(LeeAlertSheetView *)sharedInstacne{
static LeeAlertSheetView *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
-(void)showAlert:(NSString *)title message:(NSString *)message cancelTitle:(NSString *)cancelTitle viewController:(UIViewController *)vc confirm:(myAlertSheetViewBlock)confirm buttonTitles:(NSString *)buttonTitles, ...{
if (!vc) vc = RootVC;
// 讀取可變參數(shù)里面的titles數(shù)組
NSMutableArray *titleArray = [[NSMutableArray alloc] initWithCapacity:0];
va_list list;
if(buttonTitles) {
//1.取得第一個(gè)參數(shù)的值(即是buttonTitles)
[titleArray addObject:buttonTitles];
//2.從第2個(gè)參數(shù)開始,依此取得所有參數(shù)的值
NSString *otherTitle;
va_start(list, buttonTitles);
while ((otherTitle= va_arg(list, NSString*))) {
[titleArray addObject:otherTitle];
}
va_end(list);
}
if (IOS8AndLater) {
[self lee_showAlertController:title message:message cancelTitle:cancelTitle titleArray:titleArray viewController:vc confirm:confirm];
}else{
[self lee_showAlertView:title message:message cancelTitle:cancelTitle viewController:vc confirm:confirm titleArray:titleArray];
}
}
-(void)showSheet:(NSString *)title message:(NSString *)message cancelTitle:(NSString *)cancelTitle viewController:(UIViewController *)vc confirm:(myAlertSheetViewBlock)confirm buttonTitles:(NSString *)buttonTitles, ...{
if (!vc) vc = RootVC;
// 讀取可變參數(shù)里面的titles數(shù)組
NSMutableArray *titleArray = [[NSMutableArray alloc] initWithCapacity:0];
va_list list;
if(buttonTitles) {
//1.取得第一個(gè)參數(shù)的值(即是buttonTitles)
[titleArray addObject:buttonTitles];
//2.從第2個(gè)參數(shù)開始,依此取得所有參數(shù)的值
NSString *otherTitle;
va_start(list, buttonTitles);
while ((otherTitle= va_arg(list, NSString*))) {
[titleArray addObject:otherTitle];
}
va_end(list);
}
if (IOS8AndLater) {
[self lee_showSheetAlertController:title message:message cancelTitle:cancelTitle titleArray:titleArray viewController:vc confirm:confirm];
}else{
[self lee_showSheetView:title message:message cancelTitle:cancelTitle viewController:vc confirm:confirm titleArray:titleArray];
}
}
#pragma mark - ----------------內(nèi)部方法 IOS8 以后------------------
//UIAlertController(iOS8及其以后)
- (void)lee_showAlertController:(NSString *)title message:(NSString *)message cancelTitle:(NSString *)cancelTitle titleArray:(NSArray *)titleArray viewController:(UIViewController *)vc
confirm:(myAlertSheetViewBlock)confirm {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
// 下面兩行代碼 是修改 title顏色和字體的代碼
// NSAttributedString *attributedMessage = [[NSAttributedString alloc] initWithString:title attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:17.0f], NSForegroundColorAttributeName:UIColorFrom16RGB(0x334455)}];
// [alert setValue:attributedMessage forKey:@"attributedTitle"];
if (cancelTitle) {
// 取消
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
if (confirm) {
confirm(0, action.title);
}
}];
[alert addAction:cancelAction];
}
// 確定操作
if (!titleArray || titleArray.count == 0) {
UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (confirm)confirm(0,action.title);
}];
[alert addAction:confirmAction];
} else {
for (NSInteger i = 0; i<titleArray.count; i++) {
UIAlertAction *action = [UIAlertAction actionWithTitle:titleArray[i] style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (confirm)confirm(i,action.title);
}];
// [action setValue:UIColorFrom16RGB(0x00AE08) forKey:@"titleTextColor"]; // 此代碼 可以修改按鈕顏色
[alert addAction:action];
}
}
[vc presentViewController:alert animated:YES completion:nil];
}
// ActionSheet的封裝(iOS8及其以后)
- (void)lee_showSheetAlertController:(NSString *)title message:(NSString *)message cancelTitle:(NSString *)cancelTitle titleArray:(NSArray *)titleArray viewController:(UIViewController *)vc confirm:(myAlertSheetViewBlock)confirm {
UIAlertController *sheet = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleActionSheet];
if (!cancelTitle) cancelTitle = @"取消";
// 取消
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
if (confirm)confirm(cancelIndex,action.title);
}];
[sheet addAction:cancelAction];
if (titleArray.count > 0) {
for (NSInteger i = 0; i<titleArray.count; i++) {
UIAlertAction *action = [UIAlertAction actionWithTitle:titleArray[i] style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (confirm)confirm(i,action.title);
}];
[sheet addAction:action];
}
}
[vc presentViewController:sheet animated:YES completion:nil];
}
#pragma mark - ----------------內(nèi)部方法 IOS8 之前------------------
//UIAlertView
-(void)lee_showAlertView:(NSString *)title message:(NSString *)message cancelTitle:(NSString *)cancelTitle viewController:(UIViewController *)vc
confirm:(myAlertSheetViewBlock)confirm titleArray:(NSArray *)titleArray{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:title message:message delegate:self cancelButtonTitle:cancelTitle otherButtonTitles: nil];
if (confirm){
self.block = confirm;
}
[titleArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[alert addButtonWithTitle:obj];
}];
[alert show];
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (self.block) {
self.block(buttonIndex,[alertView buttonTitleAtIndex:buttonIndex]);
}
}
//UIActionSheet
-(void)lee_showSheetView:(NSString *)title message:(NSString *)message cancelTitle:(NSString *)cancelTitle viewController:(UIViewController *)vc
confirm:(myAlertSheetViewBlock)confirm titleArray:(NSArray *)titleArray{
UIActionSheet *sheet = [[UIActionSheet alloc]initWithTitle:title delegate:self cancelButtonTitle:cancelTitle destructiveButtonTitle:nil otherButtonTitles:nil];
if (confirm){
self.block = confirm;
}
[titleArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[sheet addButtonWithTitle:obj];
}];
[sheet showInView:vc.view];
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
if (self.block) {
self.block(buttonIndex,[actionSheet buttonTitleAtIndex:buttonIndex]);
}
}
@end
使用方法
[[LeeAlertSheetView sharedInstacne]showSheet:nil message:nil cancelTitle:@"取消" viewController:self confirm:^(NSInteger buttonTag,NSString *buttonTitle) {
NSLog(@"%ld-%@",buttonTag,buttonTitle);
// 你的業(yè)務(wù)邏輯根據(jù)buttonTag,buttonTitle 處理。
} buttonTitles:@"Hello",@"Lee",@"Miao", nil];