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

2017-08-01  本文已影响81人  sayHellooX

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

具体思路如下:

代码如下:

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

上一篇下一篇

猜你喜欢

热点阅读