在 UIView 上添加返回上一级操作界面(手势)

系统:手势 ——> target ----> action

自己创建的界面添加手势 :UIView —> 创建手势 —> target —> action


第一种方法

  • 获取到系统的返回上一级界面的手势,添加到 UIView 上

  • 系统的返回上一级界面的手势

    • 属于导航控制器(NavigationController),而不是 控制器UIViewController
    • 系统有一个手势属性告诉开发者当前的手势是什么
      • interactivePopGestureRecognizer: 这个就是向上一级滑动的时候,用手指从界面左边边缘向右边滑动的时候,用到的一个属性。 只能系统自己用,开发者不能使用。

第二种方法

  • 取出系统手势中的 target 和 action
  • 在自己创建的 View 上面创建一个手势,在这个手势上添加 从系统手势中取出来的 target 和 action
let panGes = UIPanGestureRecognizer(target: nil, action: nil)
view.addGestureRecognizer(panGes)

讲解一些 运行时方法
运行时的一些方法

步骤:

  • 使用运行时方法获取到手势的属性
  • class_copyIvarList(cls: AnyClass?, outCount: UnsafeMutablePointer?)
    • cls: AnyClass? : 传 UIGestureRecognizer.self
    • outCount: UnsafeMutablePointer? : 需要传入一个指针,会告诉你有多少个属性
    • var count: UInt32 = 0
    • 写好后如下:
    • class_copyIvarList(UIGestureRecognizer.self, &count)
    • 这样就可以拿到所有的 UIPanGestureRecognizer 属性

完整代码:

        var count: UInt32 = 0
        
        let ivars = class_copyIvarList(UIGestureRecognizer.self, &count)!
        
        for i in 0..<count {
            // 拿出来的是一个指针
            let nameP = ivar_getName(ivars[Int(i)])!
            // 把上面的指针转换成 string 类型
            let name = String(cString: nameP)
            print(name)
        }

打印结果

_gestureFlags
_targets
_delayedTouches
_delayedPresses
_view
_lastTouchTimestamp
_firstEventTimestamp
_state
_allowedTouchTypes
_initialTouchType
_internalActiveTouches
_forceClassifier
_requiredPreviewForceState
_touchForceObservable
_touchForceObservableAndClassifierObservation
_forceTargets
_forcePressCount
_beganObservable
_failureRequirements
_failureDependents
_activeEvents
_keepTouchesOnContinuation
_delegate
_allowedPressTypes
_name
_gestureEnvironment

我们用里面的 _targets 属性做下一个操作


   ` let targets = interactivePopGestureRecognizer?.value(forKey: "_targets")`
  • 使用 KVC 来操作
  • 可以知道 interactivePopGestureRecognizer 对应的 _targets 属性到底是什么值 --> 获取 系统手势
  • 打印结果
targets = Optional(<__NSArrayM 0x60400025fa40>(
(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7fe2ea612d60>)
)
)
  • 最外层是一个数组,因为 有多个目标 (是 targets,不是 target)
  • 所以我们可以把 targets 进行一个转换 ,转换成 NSObject 数组 as? [NSObject]
  • 数组里面存放的是对象类型 [NSObject]
let targets = interactivePopGestureRecognizer?.value(forKey: "_targets") as? [NSObject]

对 targets 进行判断,如果没有值,返回 。有值,接着往下走

 guard let targets = interactivePopGestureRecognizer?.value(forKey: "_targets") as? [NSObject] else {   return      }
  • 从数组中把对象取出来
    let targetObjc = targets[0]
    打印结果
    targetObjc = (action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7fb4205125a0>)

整体代码如下:(错误代码)

 var count: UInt32 = 0

        let ivars = class_copyIvarList(UIGestureRecognizer.self, &count)!

        for i in 0..<count {
            // 拿出来的是一个指针
            let nameP = ivar_getName(ivars[Int(i)])!
            // 把上面的指针转换成 string 类型
            let name = String(cString: nameP)
        }
       
        guard let targets = interactivePopGestureRecognizer?.value(forKey: "_targets") as? [NSObject] else {
            return
        }
        
        // 从数组中把对象取出来
        let targetObjc = targets[0]
//        print("targetObjc = \(targetObjc)")
        
        let target = targetObjc.value(forKey: "target")
        let action = targetObjc.value(forKey: "action") as? Selector
        
        let panGes = UIPanGestureRecognizer(target: target, action: action)
        view.addGestureRecognizer(panGes)
  • 上面代码会崩溃:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIGestureRecognizerTarget 0x600000232f80> valueForUndefinedKey:]: this class is not key value coding-compliant for the key action.'

因为打印的 action 里面其实是方法名字,所以可以直接用 Selector 包装方法名字。
上面的方法只需要修改
let action = Selector(("handleNavigationTransition:"))

猜你喜欢

转载自blog.csdn.net/M316625387/article/details/82966080