iOS开发 UIAlertView与UIActionSheet替换方案之SDAlertView与SDActionSheet

server/2024/12/19 1:07:04/

iOS开发 UIAlertView与UIActionSheet替换方案之SDAlertView与SDActionSheet

由于在iOS开发中,项目中还在使用UIAlertView与UIActionSheet,由于这两个类在iOS开始废弃

UIKIT_EXTERN API_DEPRECATED(“UIAlertView is deprecated. Use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert instead”, ios(2.0, 9.0)) API_UNAVAILABLE(tvos) API_UNAVAILABLE(visionos, watchos) NS_SWIFT_UI_ACTOR

需要更换成UIAlertController。UIAlertView与UIActionSheet都更换成UIAlertController,一个一个文件更改代码不太合适,更改较多,所以考虑自定义类封装UIAlertController使用。

UIAlertView与UIActionSheet

一般在UIAlertView中,我们会使用initWithTitle方法进行初始化

  • (instancetype)initWithTitle:(nullable NSString )title message:(nullable NSString )message delegate:(nullable id //)delegate cancelButtonTitle:(nullable NSString *)cancelButtonTitle otherButtonTitles:(nullable NSString *)otherButtonTitles, … NS_REQUIRES_NIL_TERMINATION;

然后使用其代理方法UIAlertViewDelegate的方法

  • (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex API_DEPRECATED(“Use UIAlertController instead.”, ios(2.0, 9.0)) API_UNAVAILABLE(visionos, watchos);
    在该方法处理点击事件。

UIActionSheet和UIAlertView使用方式类似。

封装UIAlertController

在工程中直接替换会更改太多,那这时候我这边考虑封装UIAlertController进行,封装后的类SDAlertView
虽然类名SDAlertView,但是其实继承NSObject,其中封装UIAlertController进行使用。

  • 初始化方法initWithTitle
- (instancetype)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION;
  • 创建delegate及新增方法

@protocol SDAlertViewDelegate <NSObject>- (void)alertView:(SDAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;@end
  • show方法
通过获取keyWindow的rootViewController来展示UIAlertController

完整代码如下
SDAlertView.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "UIAlertAction+SDIndex.h"@protocol SDAlertViewDelegate;
@interface SDAlertView : NSObject@property (nonatomic, weak) id<SDAlertViewDelegate>delegate;@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *message;   // secondary explanation text
@property (nonatomic) NSInteger tag;                // default is 0- (instancetype)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION;- (NSString *)buttonTitleAtIndex:(NSInteger)buttonIndex;- (void)show;@end@protocol SDAlertViewDelegate <NSObject>- (void)alertView:(SDAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex;@end

SDAlertView.m

#import "SDAlertView.h"@interface SDAlertView ()@property (nonatomic, copy) NSString *cancelButtonTitle;
@property (nonatomic, copy) NSArray *otherButtonTitleList;
@property (nonatomic, copy) NSArray *allBtnTitleList;@property (nonatomic, strong) UIAlertController *alertController;@end@implementation SDAlertView- (instancetype)init
{self = [super init];if (self) {if (sd_alertSheets == nil) {sd_alertSheets = [NSMutableArray arrayWithCapacity:0];}}return self;
}- (instancetype)initWithTitle:(NSString *)title message:(NSString *)message delegate:(id)delegate cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION; {self = [self init];if (self) {self.delegate = delegate;self.title = title;self.message = message;self.cancelButtonTitle = cancelButtonTitle;NSMutableArray *tmpTitleList = [NSMutableArray arrayWithCapacity:0];if (otherButtonTitles) {[tmpTitleList addObject:otherButtonTitles];// 后面的不定参数,可以使用va_list来获取//va_list 是一个指针变量  本质上是一个指针va_list arg_lists;//初始化 va_listva_start(arg_lists, otherButtonTitles);NSString * obj = nil;//va_arg(arg_lists, NSString*)用户来获取值while((obj=va_arg(arg_lists, NSString*))){if (obj && obj.length > 0) {[tmpTitleList addObject:[NSString stringWithFormat:@"%@", obj]];}};//结束参数获取va_end(arg_lists);}self.otherButtonTitleList = [NSArray arrayWithArray:tmpTitleList];// 所有按钮titleNSMutableArray *tmpAllTitles = [NSMutableArray arrayWithCapacity:0];if (self.cancelButtonTitle && [self.cancelButtonTitle isKindOfClass:[NSString class]] && self.cancelButtonTitle.length) {[tmpAllTitles addObject:self.cancelButtonTitle];}[tmpAllTitles addObjectsFromArray:self.otherButtonTitleList];self.allBtnTitleList = tmpAllTitles;// 初始化AlertController[self setupAlertView];// 采用这种方式,当点击的时候,将其从列表移除,防止在调用handleAlertAction时候self被释放掉了。// 调用handleAlertAction,将其从数组中移除,移除后自动调用dealloc方法[sd_alertSheets addObject:self];NSLog(@"sd_alertSheets:%@", sd_alertSheets);}return self;
}- (void)setupAlertView {self.alertController = [UIAlertController alertControllerWithTitle:self.titlemessage:self.messagepreferredStyle:UIAlertControllerStyleAlert];__block BOOL hasCancelBtn = NO;__weak typeof(self) weakSelf = self;if (self.cancelButtonTitle && [self.cancelButtonTitle isKindOfClass:[NSString class]] && self.cancelButtonTitle.length) {hasCancelBtn = true;__block int buttonIndex = 0;UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:self.cancelButtonTitlestyle:UIAlertActionStyleCancelhandler:^(UIAlertAction * _Nonnull action) {[weakSelf handleAlertAction:action buttonIndex:action.actionIndex];}];cancelAction.actionIndex = buttonIndex;[self.alertController addAction:cancelAction];}for (int i = 0; i < self.otherButtonTitleList.count; i++) {__block int buttonIndex = i + (hasCancelBtn?1:0);NSString *title = [self.otherButtonTitleList objectAtIndex:i];UIAlertAction *alertAction = [UIAlertAction actionWithTitle:titlestyle:UIAlertActionStyleDefaulthandler:^(UIAlertAction * _Nonnull action) {[weakSelf handleAlertAction:action buttonIndex:action.actionIndex];}];alertAction.actionIndex = buttonIndex;[self.alertController addAction:alertAction];}
}- (NSString *)buttonTitleAtIndex:(NSInteger)buttonIndex {if (self.allBtnTitleList && (buttonIndex < self.allBtnTitleList.count)) {NSString *title = [self.allBtnTitleList objectAtIndex:buttonIndex];return title;}return nil;
}- (void)show {if (!self.alertController) {return;}UIViewController *topViewController = UIApplication sharedApplication].keyWindow.rootViewController;[topViewController presentViewController:self.alertController animated:YES completion:^{DLog(@"SDAlertView did show completion");}];
}- (void)handleAlertAction:(UIAlertAction *)alertAction buttonIndex:(NSInteger)buttonIndex {DLog(@"handleAlertAction alertAction:%@ buttonIndex:%ld", alertAction, buttonIndex);if (self.delegate && [self.delegate respondsToSelector:@selector(alertView:clickedButtonAtIndex:)]) {[self.delegate alertView:self clickedButtonAtIndex:buttonIndex];}// 点击后再让其调用deallocif ([sd_alertSheets containsObject:self]) {[sd_alertSheets removeObject:self];}
}- (void)dealloc {DLog(@"SDAlertView dealloc");
}@end

不定参数获取

在初始化方法initWithTitle中,我们需要获取不定参数,这里通过va_list指针,获取参数代码如下

// 后面的不定参数,可以使用va_list来获取//va_list 是一个指针变量  本质上是一个指针va_list arg_lists;//初始化 va_listva_start(arg_lists, otherButtonTitles);NSString * obj = nil;//va_arg(arg_lists, NSString*)用户来获取值while((obj=va_arg(arg_lists, NSString*))){if (obj && obj.length > 0) {[tmpTitleList addObject:[NSString stringWithFormat:@"%@", obj]];}};//结束参数获取va_end(arg_lists);

静态sd_alertSheets和UIAlertAction扩展

sd_alertSheets是一个静态数组,使用sd_alertSheets是为了保证SDAlertView在代理事件处理后再释放SDAlertView对象,调用其dealloc方法。

// 采用这种方式,当点击的时候,将其从列表移除,防止在调用handleAlertAction时候self被释放掉了。
// 调用handleAlertAction,将其从数组中移除,移除后自动调用dealloc方法

UIAlertAction为增加属性,动态增加属性,一般采用runtime的方法。

#import <UIKit/UIKit.h>static NSMutableArray *sd_alertSheets;@interface UIAlertAction (SDIndex)@property (nonatomic, assign) NSInteger actionIndex;@end
#import "UIAlertAction+SDIndex.h"static void *kActionIndexStrKey = &kActionIndexStrKey;@implementation UIAlertAction (CSExt)- (NSInteger)actionIndex {NSNumber *actionIndxNum = objc_getAssociatedObject(self, kActionIndexStrKey);return [actionIndxNum integerValue];
}- (void)setActionIndex:(NSInteger)actionIndex {objc_setAssociatedObject(self, kActionIndexStrKey, [NSNumber numberWithInteger:actionIndex], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}@end

封装好SDAlertView类,替换工程UIAlertView

封装好SDAlertView类,替换工程UIAlertView,这时候,我们可以全局替换掉系统的UIAlertView,将UIAlertView替换成SDAlertView即可。

当然系统中的UIActionSheet替换方式一样,可以自定义类SDActionSheet采用同样的方式替换。

对于一些方法addButtonWithTitle、buttonTitleAtIndex、cancelButtonIndex您也可以尝试新增一些方法完善一下。

小结

iOS开发 在处理一些代码时候,自己常用的做法做一层封装,方便统一管理与替换。https://blog.csdn.net/gloryFlow/article/details/144538615


http://www.ppmy.cn/server/151307.html

相关文章

宝塔SSL证书申请失败,报错:申请SSL证书错误 module ‘OpenSSL.crypto‘ has no attribute ‘sign‘(已解决)

刚安装宝塔申请SSL就报错&#xff1a;申请SSL证书错误 module OpenSSL.crypto has no attribute sign 面板、插件版本&#xff1a;9.2.0 系统版本&#xff1a;Alibaba Cloud Linux 3.2104 LTS 问题&#xff1a;申请SSL证书错误 module OpenSSL.crypto has no attribute sign…

医疗 UI 设计如何精准传达复杂的健康数据?

在医疗环境中&#xff0c;患者往往承受着身体不适和心理压力&#xff0c;医疗 UI 设计的色彩搭配因此具有了特殊且重要的意义。合适的色彩组合能够营造出宁静、安心的氛围&#xff0c;有助于舒缓患者的紧张与焦虑情绪&#xff0c;促进其康复过程。 蓝色系常常被视为医疗 UI 设…

在完全不连外网的 Linux 服务器里更新 docker compose

docker compose 的 develop.watch 属性至少要 2.22.0 版本 故参考&#xff1a;docs.docker.com/compose/install/linux/#install-the-plugin-manual… Linux 服务器 输入 uname -a 查看架构信息 在能连外网的电脑上下载 OS 对应版本的 compose 可执行文件 访问 github.com/do…

Python 默认 Logging 级别及其示例

Python 默认 Logging 级别及其示例 在开发Python应用程序时&#xff0c;日志记录&#xff08;Logging&#xff09;是调试和监控程序运行状态的重要工具。Python的logging模块提供了一种灵活且强大的方式来记录应用程序的信息。本文将详细介绍Python logging模块的默认级别&…

Java安全—SpringBootActuator监控泄露Swagger自动化

前言 今天依旧是SpringBoot框架&#xff0c;估计还要一篇文章才能把它写完&#xff0c;没办法&#xff0c;Java安全的内容太多了。 Actuator SpringBoot Actuator模块提供了生产级别的功能&#xff0c;比如健康检查&#xff0c;审计&#xff0c;指标收集&#xff0c;HTTP跟踪…

Javaweb:HTML、CSS

学习 资源1 学习资源 2 黑马javaweb HTML 1、基础标签、样式 图片标签&#xff1a;<img> src:绝对路径、相对路径(绝对磁盘路径&#xff0c;网络路径&#xff1b;./当前目录&#xff09;width:宽度&#xff08;百分比&#xff09;height:高度&#xff08;百分比&…

09篇--图片的水印添加(掩膜的运用)

如何添加水印&#xff1f; 添加水印其实可以理解为将一张图片中的某个物体或者图案提取出来&#xff0c;然后叠加到另一张图片上。具体的操作思想是通过将原始图片转换成灰度图&#xff0c;并进行二值化处理&#xff0c;去除背景部分&#xff0c;得到一个类似掩膜的图像。然后…

【数据分享】2013-2023年我国省市县三级的逐年CO数据(免费获取\excel\shp格式)

空气质量数据是在我们日常研究中经常使用的数据&#xff01;之前我们给大家分享了2000-2023年的省市县三级的逐年PM2.5数据、2000-2023年的省市县三级的逐年PM10数据、2013-2023年的省市县三级的逐年SO2数据、2000-2023年省市县三级的逐年O3数据和2008-2023年我国省市县三级的逐…