Swift中通过运行时实现全屏的pop功能

news/2024/7/24 13:12:07 标签: swift

最近碰见个小的功能需求,就是需要给push的视图控制器添加一个侧滑pop弹出的功能,找了点资料,发现一个比较不错的解决办法,用了相识已久,但是没用过的运行时功能来实现。

具体思路如下:

    1. push到 UINavigationController 中的控制器视图,系统默认是给添加了一个边缘侧滑pop回上一页的方法的,这个功能是 UINavigationController 通过属性 var interactivePopGestureRecognizer: UIGestureRecognizer? 实现的
  • 2.因为 UIGestureRecognizer 都是通过target 和action来实现具体的操作的,所以我们可以将系统的这个边缘策划pop的手势,通过运行时把他的target 和action取出来添加到我们自建的手势上,完活。

代码如下:

swift copyable">//通过 class_copyIvarList() 方法获得UIGestureRecognizer的所有变量 包括 property及{ }中的
override func viewDidLoad() {
        super.viewDidLoad()
        var count: UInt32 = 0
        let ivars = class_copyIvarList(UIGestureRecognizer.self, &count)!
        for i in 0..<count {
            //获得变量的名字
            let nameP = ivar_getName(ivars[Int(i)])!
            let name = String.init(cString: nameP)
            print(name)
        }
}
//输出如下
/*
_gestureFlags
_targets
_delayedTouches
_delayedPresses
_view
_lastTouchTimestamp
_state
_allowedTouchTypes
_initialTouchType
_internalActiveTouches
_forceClassifier
_requiredPreviewForceState
_touchForceObservable
_touchForceObservableAndClassifierObservation
_forceTargets
_forcePressCount
_beganObservable
_failureRequirements
_failureDependents
_delegate
_allowedPressTypes
_gestureEnvironment
*/
复制代码

我们目测(当然要靠一点猜测了?)_targets 这个变量 应该是负责 action 和target相关的属性,所以我们通过KVC来具体查看一下

swift copyable"> let tempTargets = interactivePopGestureRecognizer?.value(forKey: "_targets")
 print(tempTargets)
//输出如下
/*
Optional(<__NSArrayM 0x60000004be80>(
(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7f88db500670>)
)
)
*/
复制代码

从输出中我们可以看出来确实有我们需要的action 和 target 我们可以通过KVC将对应的值取出来

swift copyable">        guard let targets = interactivePopGestureRecognizer?.value(forKey: "_targets") as? [NSObject] else {
            return
        }
        let targetObjct = targets.first
        let target = targetObjct?.value(forKey: "target")
        let action = targetObjct?.value(forKey: "action")
复制代码

这样取出来会造成崩溃,提示没有action这个值(为啥还真不知道...),所以将action的获取更改如下:

swift copyable">//直接通过字符进行封装
let action = Selector(("handleNavigationTransition:"))
复制代码

这样我们的目的就达到了,有了 target 和 action ,我们将target 和 action添加到对应的手势上就可以了 因为我们要求的是某一些固定push的页面都拥有这个功能,所以我们通过自定义UINavigationController,然后将这个手势添加在了UINavigationController的view上,这样所有的栈内的控制器都有这个全局pop的功能了,全部代码如下:

swift copyable">//UINavigationController 中
class CustomNavController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()
        //通过运行时获得手势中的隐藏属性
        //var interactivePopGestureRecognizer: UIGestureRecognizer? UINavigationController自带的边缘pop手势
        var count: UInt32 = 0
        let ivars = class_copyIvarList(UIGestureRecognizer.self, &count)!
        for i in 0..<count {
            let nameP = ivar_getName(ivars[Int(i)])!
            let name = String.init(cString: nameP)
            //print(name)
        }
        
        let tempTargets = interactivePopGestureRecognizer?.value(forKey: "_targets")
       // print(tempTargets)
        
        guard let targets = interactivePopGestureRecognizer?.value(forKey: "_targets") as? [NSObject] else {
            return
        }
        let targetObjct = targets.first
        let target = targetObjct?.value(forKey: "target")
        let action = Selector(("handleNavigationTransition:"))
        view.addGestureRecognizer(UIPanGestureRecognizer(target: target, action: action))
    }
}

复制代码

http://www.niftyadmin.cn/n/1120861.html

相关文章

AWS认证权威考经(助理级认证篇)

笔者作为AWS官方认证的早期通过者&#xff0c;已经拿到了AWS的助理级解决方案架构师、开发者认证&#xff0c;系统管理员认证。这几年也陆续指导公司多人通过AWS的认证。本篇文章将分享如何通过自学的方式轻松通过AWS的助理级架构师、开发者和系统管理员认证。 为什么要考证 在…

文本文件内容相关命令

1、查看文本文件内容命令cat 命令格式&#xff1a;cat [option] filename cat命令常用的选项只有v&#xff0c;其功能是显示文件内容的同时&#xff0c;也显示文件中的控制字符&#xff0c;这个选项可以非常方便的查看脚本中不能识别的控制字符。 2、从文本尾查看文本内容命令t…

转载 - Linux TC(Traffic Control)框架原理解析

近日的工作多多少少和Linux的流控有点关系&#xff0c;自打几年前知道有TC这么一个玩意儿并且多多少少理解了它的原理之后&#xff0c;我就没有再动过它&#xff0c;因为我不喜欢TC命令行&#xff0c;实在是太繁琐了&#xff0c;iptables命令行也比较繁琐&#xff0c;但是比TC命…

Dynamics CRM 后台通过组织服务获取时间字段值的准确转换

做CRM开发的都知道&#xff0c;在系统时间字段的处理上是有讲究的&#xff0c;因为数据库中存的是UTC时间&#xff0c;CRM的界面时间字段会根据个人设置中的时区以及格式自动调整&#xff0c;这是最基本的一面&#xff0c;那还有很多使用时间的场景&#xff0c;比如脚本使用ODA…

算法----(3)选择排序

记录一趟中最大&#xff08;小&#xff09;元素&#xff0c;最后再进行交换 1 def select_sort(s):2 # select_sort3 for i in range(len(s) - 1):4 min i5 for j in range(i 1, len(s)):6 if s[min] > s[j]:7 min …

容器LinkedList原理(学习)

一、概述 数据结构和ArrayList有本质不同&#xff0c;LinkedList 是基于链表实现&#xff0c;它的插入和删除操作比 ArrayList 更加高效&#xff0c;基于链表的&#xff0c;所以随机访问的效率要比 ArrayList 差。 二、数据结构 包含了 first 和 last 两个指针(Node)。Node 中包…

1.快速入门

转自&#xff1a;https://www.gruntjs.net/getting-started Grunt和 Grunt 插件是通过 npm 安装并管理的&#xff0c;npm是 Node.js 的包管理器。 Grunt 0.4.x 必须配合Node.js > 0.8.0版本使用。&#xff1b;奇数版本号的 Node.js 被认为是不稳定的开发版。 在安装 Grunt 前…

前端每日实战:87# 视频演示如何用 1 个 DOM 元素和纯 CSS 创作一台对开门冰箱...

效果预览 按下右侧的“点击预览”按钮可以在当前页面预览&#xff0c;点击链接可以全屏预览。 https://codepen.io/comehope/pen/EpWagM 可交互视频 此视频是可以交互的&#xff0c;你可以随时暂停视频&#xff0c;编辑视频中的代码。 请用 chrome, safari, edge 打开观看。 ht…