IOS-如何优雅地拦截按钮事件(判断是否需要登录)
关于这个标题,起因是这样的。
最近一次做项目需求时,遇到这样一个需求,就是本来我们App是必须注册或者第三方登录才可以使用,现在希望不登录也可以浏览App里面的内容,只是在需要的时候才提示登录,并且在用户没有登录的情况下,用户选择并登录成功了,程序需自动完成用户操作登录前的操作。比如购买商品时没有登录,用户登录成功后,直接跳转至订单确认页面。
在接到这个需求时,我们的App功能已经很多了,评估了下这个需求,发现App里面很多功能是需要登录才可以操作,比如关注用户、购买商品、私信聊天、评论等等,而且这些功能的入口也比较多。
这么多的地方我们都要去写判断的代码显然是不科学的,那么有没有简单点的方式呢?怎么避免我们去做苦力活呢?????????????
于是,进一步分析,发现这些功能大部分都是用户主动通过点击按钮来触发下一步操作。此时,我们把关注点移到按钮UIButton上。
最开始想到的办法是自定义一个button,让所有需要登录操作的按钮继承这个按钮,然后,在这个按钮里面拦截自身事件进一步处理。但是,发现这么做还是需要改大量的代码。接着想到用类别来做,这样直接给按钮增加一个BOOL属性,设置为YES的按钮视为需要做登录才可以操作的按钮。然后,对于需要登录操作的按钮,在分类里面拦截其点击事件,并记录target和action,然后先判断是否登录:如果没有登录则丢弃其target和action,并且提示用户登录;如果用户已经登录或者登录成功了,则继续让target执行action,这样完美解决我们的需求,也只需要很少的代码即可搞定。
这个方案看似很不错,不过在实际做的时候还是走了弯路。一开始,我们想从下面方法入手
|
1
|
- (void)addTarget:(nullableid)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents |
但是发现根本就不能实现。经过查找,找到了下面这个方法:
|
1
|
- (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event |
关于这个方法,苹果给了如下解释:
send the action. the first method is called for the event and is a point at which you can observe or override behavior. it is called repeately by the second.
这正是我们要找的方法,于是我们重写此方法,如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
- (void)sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event{ if (self.checkLogin) { self.selector = NSStringFromSelector(action); self.objClass = target; [self checkIsLogin]; } else { [super sendAction:action to:target forEvent:event]; }}- (void)checkIsLogin{ __weak typeof(self) weakSelf = self; [LoginManager checkLoginSuccess:^{ SEL sel = NSSelectorFromString(weakSelf.selector); if ([weakSelf.objClass respondsToSelector:sel]) { if ([weakSelf.selector hasSuffix:@":"]) { objc_msgSend(weakSelf.objClass, sel, self); } else { objc_msgSend(weakSelf.objClass, sel); } } }];} |
简单解释下这段代码:
当按钮事件执行时会走sendAction:to:forEvent:这个方法,于是,我们在这个方法里面,先判断该按钮是否需要登录后再操作,如果需要,阻断事件传递,并记录下按钮的action和target,然后判断是否登录了,如果已经登录或者用户登录成功了,那么再调用objc_msgSend(self.objClass, self.selector)去实现按钮事件,如果用户放弃登录或者登录失败,则不做处理。
实现了上面的方法之后,我们只需要找出那些按钮事件需要登录后才能操作,然后,设置按钮的checkLogin = YES即可,这样是不是省了很多不必要的代码。
到此,上面的实现已经解决了所有按钮点击需要判断登录的操作。还有些是上述方式解决不了的,则使用LoginManager单独处理下,幸运的是,几乎很少地方需要单独处理。
通过这个案例:一方面巩固了对sendAction:to:forEvent:这个方法的理解;另一方面在做需求的时候一定要发散思维,找到更合理的解决方法。
欢迎大家留言讨论,如果你有更好地方法,欢迎分享!
IOS-如何优雅地拦截按钮事件(判断是否需要登录)的更多相关文章
- springMvc实现拦截特定请求判断用户是否登录
流程: 新建一个拦截器,配置拦截哪些,放行哪些 在spring servrt中配置拦截器 <!--配置拦截器--> <mvc:interceptors> <!--登录拦截 ...
- 拦截iOS系统导航栏返回按钮事件-三种方法
方法一:在dealloc里面书写监听事件,因为只有pop才会调用dealloc,push不会掉用 - (void)dealloc {YLLog(@"123"); } 方法二:在- ...
- IOS第四天(5:创建备份区按钮和判断结果)
创建备份区按钮和判断结果 /** 创建备选区按钮 */ - (void)createOptionButtons:(HMQuestion *)question { // 问题:每次调用下一题方法时,都会 ...
- iOS代码实现:创建按钮,绑定按钮事件,读取控件值
// // main.m // Hello // // Created by lishujun on 14-8-28. // Copyright (c) 2014年 lishujun. All rig ...
- iOS 用RunTime来提升按钮的体验
用RunTime来提升按钮的体验 载请标明出处:http://blog.csdn.net/sk719887916/article/details/52597388,作者:Ryan 经常处理按钮问题都是 ...
- iOS头条新闻App、自动布局、省市区联动、登录按钮动画、Alert弹框效果等源码
iOS精选源码 LEEAlert -- 优雅的Alert ActionSheet 登录按钮 省市区三级联动 JHViewCorner - 一行代码搞定圆角 JHFrameLayout - 一行代码实现 ...
- asp.net中用回车代替按钮事件
第一步,先编写简单的页面代码,这里我们只需要一个按钮就足够了.当然,还有按钮事件. <html> <head> <title>测试绑定enter</title ...
- Android中Touch事件分析--解决HorizontalScrollView滑动和按钮事件触发问题
之前写过关于HorizontalScrollView滑动和按钮事件触发问题,但是不能所有的情况,最近几天一直在想这个问题,今天有一个比较好的解决思路,最终应用在项目里面效果也很好,首先说明一下功能: ...
- Java知多少(82)标签、按钮和按钮事件简介
标签和按钮也许是图形界面中最常见的两种组件,按钮又总是与激发动作事件有关. 标签 标签(JLabel)是最简单的Swing组件.标签对象的作用是对位于其后的界面组件作说明.可以设置标签的属性,即前景色 ...
随机推荐
- Scala简介及基础语法
一.scala简介 官网:https://www.scala-lang.org/ Scala语言很强大,集成了面向对象和函数式编程的特点. 运行在JVM(jdk). 大数据中为什么学习scala? s ...
- pandas 从txt读取DataFrame&DataFrame格式化保存到txt
前提 首先保证你txt里的文本内容是有规律可循的(例如,列与列之间通过“\t”.“,”等指定的可识别分隔符分隔): 例如我需要读取的数据,(\t)分隔: (此文件内容是直接以DataFrame格式化写 ...
- python分段算利润、税收
''' 题目:企业发放的奖金根据利润提成. 利润(I)低于或等于10万元时,奖金可提10%: 利润高于10万元,低于20万元时,低于10万元的部分按10%提成,高于10万元的部分,可提成7.5%: 2 ...
- centos linux系统日常管理复习 CPU物理数逻辑核数,iftop ,iotop ,sar ,ps,netstat ,一网卡多IP,mii-tool 连接,ethtool速率,一个网卡配置多个IP,mii-tool 连接,ethtool速率 ,crontab备份, 第十八节课
centos linux系统日常管理复习 物理CPU和每颗CPU的逻辑核数,uptime ,w,vmstat,iftop ,iotop ,sar ,ps,netstat ,一个网卡配置多个IP,mii ...
- DIY自己的GIS程序(1)——起航
一个GIS系统最重要的功能是绘制图形和关联属性,这里研究二维点线面的绘制过程: 对于一个绘图系统设计,图形的绘制涉及两个重要的方面. 1.一个是绘制或者重新绘制,重绘过程出现在下面情况: a 界面初始 ...
- Java模板模式
模板类 package com.ietree.designpattern.template; /** * 模板类 * * @author Root */ public abstract class S ...
- 图:无向图(Graph)基本方法及Dijkstra算法的实现 [Python]
一般来讲,实现图的过程中需要有两个自定义的类进行支撑:顶点(Vertex)类,和图(Graph)类.按照这一架构,Vertex类至少需要包含名称(或者某个代号.数据)和邻接顶点两个参数,前者作为顶点的 ...
- pyDay16
内容来自廖雪峰的官方网站. 1.Python内建的filter()函数用于过滤序列. 2.和map()类似,filter()也接收一个函数和一个序列.和map()不同的是,filter()把传入的函数 ...
- 20145312 《网络对抗》PC平台逆向破解:注入shellcode和 Return-to-libc 攻击实验
20145312 <网络对抗>PC平台逆向破解:注入shellcode和 Return-to-libc 攻击实验 注入shellcode 实验步骤 1. 准备一段Shellcode 2. ...
- 20145322何志威《网络对抗》逆向及Bof基础
20145322何志威<网络对抗>逆向及Bof基础 实践目标 本次实践的对象是一个名为pwn1的linux可执行文件. 该程序正常执行流程是:main调用foo函数,foo函数会简单回显任 ...