跟iOS UI的捉迷藏(如何获取用户点击行为的控件title)

近期,接到一个需求,需要获取用户点击行为的操作路径,除了点击的坐标,classname等常用数据外,还需要控件的title,这样就可以更加直观的了解到用户的操作行为。

乍一听,熟悉Android的同学会说, View的onClick事件监听就好了,然而,iOS与Android并不相同,一方面,iOS没有统一的获取title的方式,另一方面,不同UI控件title的位置不尽相同,所以,要想获取常用控件的的title,着实需要对控件的层级结构有一定的了解,本文目前只对常用的7个控件进行介绍,后期可能会增加,欢迎大家一起探讨尝试,如有留言案例我会一起尝试。

1.如何获取用户控件的点击行为

事实上,由于获取的“所见所得”点击view行为,所以,思路上应该是对uiview或者及其子类得某个事件方法hook到,这样触发点击(广义上是触摸)行为后,可以根据发送的事件确定点击的UI控件类型,进一步获取对应title

事实上,具体流程比较复杂,如下图:

这里有篇文章讲的比较详细:

https://www.jianshu.com/p/ae6466d3e89e 里面不仅讲了整个流程,还对不同控件的优先顺序进行了说明,这对比较复杂的自定义的UI是比较重要的。

根据上文可知,当UIControl监听到需要处理的交互事件时,会调用 sendAction:to:forEvent: 将target、action以及event对象发送给全局应用,Application对象再通过 sendAction:to:from:forEvent: 向target发送action。

我们只需要通过hook UIControl的 sendAction:to:forEvent: 或 sendAction:to:from:forEvent: 自定义事件执行的target及action。

这里我们用第一个,sendAction:to:forEvent:

里面有三个参数,最后一个是event,可以通过allTouches方法,可以获得触摸点的集合,可以判断多点触摸事件

而touch.view或touch.window可以获取对应的uiview或者uiwindow

对应的点击位置信息可以用过 [uiTouch locationInView:uiTouch.view]获取;

这样我们就能对uiview进行判断,并获取title了

触摸事件参考文章:https://www.cnblogs.com/syxchina/archive/2012/10/14/2723541.html

2.如何获取不同控件的title

至此,我们可以获取到uiview,这里就需要判断目标是uiview的哪个子类

没错,iOS没有统一的title获取方式,所以要对每种控件单独判断。。。

先从简单的开始

一阶获取的控件:UIButton

响应的uiview是UIButton,即用户点击的是按钮,则立马获取(即一阶获取)

NSString * title = [[button titleLabel] text];

下面加大难度,获取UITableView的cell内容

二阶获取的控件:UITableView的cell

通过上面的方法,当用户点击了红色字体的内容后,响应的view是UITableViewCellContentView

这个方法与UITableView的关系如下:

这里有两种方法,一种是获取UITableViewCellContentView的subview,再获取label的text,也可以获取UITableViewCellContentView的superview,通过[[uitableview textLabel] text]方法获得,拐了一个弯,需要父view或子view,即二阶获取

二阶获取的控件:UITabBar

UITabBar也是一个常用的布局

层级关系如下:

向下一层即可获取,也是二阶获取

 

下面继续,获取页面上面的button(UINavigationController的leftBarButtonItem和rightBarButtonItems)

三阶获取的控件:UINavigationController的leftBarButtonItem、rightBarButtonItems

通过上面响应的uiview是_UIButtonBarButton(注意下划线)

查询层级结构如下:

从上图可知需要获取_UIButtonBarButton子view(_UIModernBarButton)的子view,即UIButtonLabel,才能获取title,即三阶获取

四阶获取的控件:UINavigationController的backButton

还有一个跟它类似的地方,即vc的返回按钮

层级关系如下:

虽然响应的都是_UIModernBarButton,但子view是_UIBackButtonContainerView,再是_UIModernBarButton,再是UIButtonLabel,可以称为四阶获取

五阶获取的控件:UIswitch

下一个UIswitch,UIswitch比较特殊,它本身没有title,但一般都与某个cell合并使用,所以直接获取父view的cell的title

层级关系如下:

这里响应的view比较靠下,需要一直向上找4层,再向下找1层,才能找到ULTableViewLabel,所以为五阶获取

平行获取的控件:UINavigationController的backButton

这是个比较有意思的空间,点击UICollectionViewCell,响应的是一个UIView

层级关系如下:

它与UILabel是平行的,获取的方法是先找到父viewUICollectionViewCell,再找到其子view,才可以

错位获取,UISegmentedControl

通过上面的获取,基本上把父view和子view的关系搞清,层级可能比较多,但都可获取,但UISegmented是个例外

当我们点击“家具”这个segment时,获取是UISegmentedControl

层级关系如下:

UISegmentedControl里面有好几个UISegment。。。。。。

这样就无法确定是哪个UISegment

换条路

通过打印UISegmentedControl的方法列表,我们找到了一个selectedSegmentIndex

这个对应的内容为最后一个被选中的UISegment,额,所以当用户点击任何一个UISegment时,我们可以获得前一个UISegment,即离开的UISegment是哪个。

难道真的没有SegmentIndex可以获取吗?

查官方文档

找到了一个,但是iOS14才开放的方法

可以升级后好好试一下,如果大家有好的方法获取,请留言。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值