系统:手势 ——> 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:"))