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

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.mzph.cn/news/890336.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Iris简单实现Go web服务器

package mainimport ("github.com/kataras/iris" )func main() {app : iris.New() // 实例一个iris对象//配置路由app.Get("/", func(ctx iris.Context) {ctx.WriteString("Hello Iris")})app.Get("/aa", func(ctx iris.Context) {ct…

tryhackme-Pre Security-HTTP in Detail(HTTP的详细内容)

任务一&#xff1a;What is HTTP(S)?&#xff08;什么是http&#xff08;s&#xff09;&#xff09; 1.What is HTTP? (HyperText Transfer Protocol)&#xff08;什么是 HTTP&#xff1f;&#xff08;超文本传输协议&#xff09;&#xff09; http是你查看网站的时候遵循的…

【C++11】可变模板参数

目录 可变模板的定义方式 参数包的展开方式 递归的方式展开参数包 STL中的emplace相关接口函数 STL容器中emplace相关插入接口函数 ​编辑 模拟实现&#xff1a;emplace接口 C11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板&#xff0c;相比 C9…

springmvc的拦截器,全局异常处理和文件上传

拦截器: 拦截不符合规则的&#xff0c;放行符合规则的。 等价于过滤器。 拦截器只拦截controller层API接口。 如何定义拦截器。 定义一个类并实现拦截器接口 public class MyInterceptor implements HandlerInterceptor {public boolean preHandle(HttpServletRequest reque…

ECharts热力图-笛卡尔坐标系上的热力图,附视频讲解与代码下载

引言&#xff1a; 热力图&#xff08;Heatmap&#xff09;是一种数据可视化技术&#xff0c;它通过颜色的深浅变化来表示数据在不同区域的分布密集程度。在二维平面上&#xff0c;热力图将数据值映射为颜色&#xff0c;通常颜色越深表示数据值越大&#xff0c;颜色越浅表示数…

EE308FZ_Sixth Assignment_Beta Sprint_Sprint Essay 3

Assignment 6Beta SprintCourseEE308FZ[A] — Software EngineeringClass Link2401_MU_SE_FZURequirementsTeamwork—Beta SprintTeam NameFZUGOObjectiveSprint Essay 3_Day5-Day6 (12.15-12.16)Other Reference1. WeChat Mini Program Design Guide 2. Javascript Style Guid…

JVM 详解

一. JVM 内存区域的划分 1. 程序计数器 程序计数器是JVM中一块比较小的空间, 它保存下一条要执行的指令的地址. [注]: 与CPU的程序计数器不同, 这里的下一条指令不是二进制的机器语言, 而是Java字节码. 2. 栈 保存方法中的局部变量, 方法的形参, 方法之间的调用关系. 栈又…

基于 uniapp 开发 android 播放 webrtc 流

一、播放rtsp协议流 如果 webrtc 流以 rtsp 协议返回&#xff0c;流地址如&#xff1a;rtsp://127.0.0.1:5115/session.mpg&#xff0c;uniapp的 <video> 编译到android上直接就能播放&#xff0c;但通常会有2-3秒的延迟。 二、播放webrtc协议流 如果 webrtc 流以 webrt…

frp内网穿透部署及使用

frp是什么 frp 是一款开源的高性能的反向代理应用&#xff0c;专注于内网穿透&#xff0c;它采用 C/S 模式&#xff0c;将服务端部署在具有公网 IP 的机器上&#xff0c;客户端部署在内网或防火墙内的机器上&#xff0c;通过访问暴露在服务器上的端口&#xff0c;反向代理到处…

基于MATLAB的图像增强

目录 一、背景及意义介绍背景图像采集过程中的局限性 意义 二、概述三、代码结构及说明&#xff08;一&#xff09;整体结构&#xff08;二&#xff09;亮度增强部分&#xff08;三&#xff09;对比度增强部分&#xff08;四&#xff09;锐度增强部分 四、复现步骤&#xff08;…

本地部署webrtc应用怎么把http协议改成https协议?

环境&#xff1a; WSL2 Ubuntu22.04 webrtc视频聊天应用 问题描述&#xff1a; 本地部署webrtc应用怎么把http协议改成https协议&#xff1f; http协议在安卓手机浏览器上用不了麦克风本&#xff0c;来地应用webrtc 本来是http协议&#xff0c;在安卓手机上浏览器不支持使…

重撸设计模式--代理模式

文章目录 定义UML图代理模式主要有以下几种常见类型&#xff1a;代理模式涉及的主要角色有&#xff1a;C 代码示例 定义 代理模式&#xff08;Proxy Pattern&#xff09;属于结构型设计模式&#xff0c;它为其他对象提供一种代理以控制对这个对象的访问。 通过引入代理对象&am…

重拾设计模式--组合模式

文章目录 1 、组合模式&#xff08;Composite Pattern&#xff09;概述2. 组合模式的结构3. C 代码示例4. C示例代码25 .应用场景 1 、组合模式&#xff08;Composite Pattern&#xff09;概述 定义&#xff1a;组合模式是一种结构型设计模式&#xff0c;它允许你将对象组合成…

全志H618 Android12修改doucmentsui功能菜单项

背景: 由于当前的文件管理器在我们的产品定义当中,某些界面有改动的需求,所以需要在Android12 rom中进行定制以符合当前产品定义。 需求: 在进入File文件管理器后,查看...功能菜单时,有不需要的功能菜单,需要隐藏,如:新建窗口、不显示的文件夹、故代码分析以及客制…

Mapbox-GL 的源码解读的一般步骤

Mapbox-GL 是一个非常优秀的二三维地理引擎&#xff0c;随着智能驾驶时代的到来&#xff0c;应用也会越来越广泛&#xff0c;关于mapbox-gl和其他地理引擎的详细对比&#xff08;比如CesiumJS&#xff09;&#xff0c;后续有时间会加更。地理首先理解 Mapbox-GL 的源码是一项复…

移动网络(2,3,4,5G)设备TCP通讯调试方法

背景&#xff1a; 当设备是移动网络设备连接云平台的时候&#xff0c;如果服务器没有收到网络数据&#xff0c;移动物联设备发送不知道有没有有丢失数据的时候&#xff0c;需要一个抓取设备出来的数据和服务器下发的数据的方法。 1.服务器系统是很成熟的&#xff0c;一般是linu…

jmeter中的prev对象

在jmeter中通过beanshell、JSR223的各种处理器编写脚本时&#xff0c;都会看到页面上有这样的说明 这些ctx、vars、props、OUT、sampler、prev等等都是可以直接在脚本中使用的对象&#xff0c;由jmeter抛出 今天主要讲一下prev的使用 SampleResult prev jmctx.getPreviousRe…

异步BUCK二极管损耗计算

异步BUCK工作原理 Q闭合时&#xff08;Ton&#xff09;&#xff0c;输入电压Vin为电感L和输出电容Cout充电&#xff0c;同时为负载供电&#xff1b;Q断开时&#xff08;Toff&#xff09;&#xff0c;电感L为负载供电&#xff0c;电流通过续流二极管D回流到电感L&#xff1b; 之…

跨站脚本攻击的多种方式——以XSS-Labs为例二十关详解解题思路

一、XSS-Labs靶场环境搭建 1.1、XSS介绍 跨站脚本攻击&#xff08;XSS&#xff09;_跨站脚本测试-CSDN博客https://coffeemilk.blog.csdn.net/article/details/142266454 1.2、XSS-Labs XSS-Labs是一个学习XSS攻击手法的靶场&#xff0c;方便我们系统性的学习掌握跨站脚本攻击…

html+css网页设计 美食 蛋糕美食7个页面

htmlcss网页设计 美食 蛋糕美食7个页面 网页作品代码简单&#xff0c;可使用任意HTML辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&#xf…