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

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

具体思路如下:

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

代码如下:

//通过 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来具体查看一下

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

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

        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的获取更改如下:

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

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

//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))
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值