İOS 13.4 için güncellendi
iOS 13.4 önceki çözümü bozdu, bu yüzden işler çirkinleşecek. Görünüşe göre iOS 13.4'te bu davranış artık özel bir yöntemle kontrol ediliyor _gestureRecognizer:shouldReceiveEvent:
( shouldReceive
iOS 13.4'te eklenen yeni genel yöntemle karıştırılmamalıdır).
Temsilciyi geçersiz kılan veya sıfır olarak ayarlayan diğer yayınlanmış çözümlerin bazı beklenmedik davranışlara neden olduğunu buldum.
Benim durumumda, gezinme yığınının tepesindeyken ve hareketi bir tane daha patlatmak için kullanmaya çalıştığımda, başarısız olurdu (beklendiği gibi), ancak daha sonra yığına itme girişimleri, gezinti çubuğu. Bu mantıklıdır, çünkü temsilci, gezinme çubuğu gizlendiğinde hareketin tanınmasını engelleyip engellemekten daha fazlasını ele almak için kullanılıyor ve diğer tüm davranışlar atılıyordu.
Benim testlerime göre, gestureRecognizer(_:, shouldReceiveTouch:)
orijinal temsilcinin hareketin gezinme çubuğu gizlendiğinde tanınmasını engellemek için uyguladığı yöntem olduğu anlaşılıyor gestureRecognizerShouldBegin(_:)
. gestureRecognizerShouldBegin(_:)
Temsilci çalışmalarında uygulayan diğer çözümler, çünkü bir uygulamasının olmaması, gestureRecognizer(_:, shouldReceiveTouch:)
tüm dokunuşları almanın varsayılan davranışına neden olacaktır.
@Nathan Perry'nin çözümü yaklaşıyor, ancak respondsToSelector(_:)
temsilciye mesajlar gönderen UIKit kodu uygulaması olmadan , diğer delege yöntemlerinin hiçbiri için uygulama olmadığına inanacak ve forwardingTargetForSelector(_:)
asla çağrılmayacaktır.
Bu nedenle, davranışı değiştirmek istediğimiz belirli bir senaryoda `jestRecognizer (_ :, shouldReceiveTouch :) kontrolünü ele alıyoruz ve diğer her şeyi temsilciye iletiyoruz.
class AlwaysPoppableNavigationController : UINavigationController {
private var alwaysPoppableDelegate: AlwaysPoppableDelegate!
override func viewDidLoad() {
super.viewDidLoad()
self.alwaysPoppableDelegate = AlwaysPoppableDelegate(navigationController: self, originalDelegate: self.interactivePopGestureRecognizer!.delegate!)
self.interactivePopGestureRecognizer!.delegate = self.alwaysPoppableDelegate
}
}
private class AlwaysPoppableDelegate : NSObject, UIGestureRecognizerDelegate {
weak var navigationController: AlwaysPoppableNavigationController?
weak var originalDelegate: UIGestureRecognizerDelegate?
init(navigationController: AlwaysPoppableNavigationController, originalDelegate: UIGestureRecognizerDelegate) {
self.navigationController = navigationController
self.originalDelegate = originalDelegate
}
@objc func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if let navigationController = navigationController, navigationController.isNavigationBarHidden && navigationController.viewControllers.count > 1 {
return true
}
else if let originalDelegate = originalDelegate {
return originalDelegate.gestureRecognizer!(gestureRecognizer, shouldReceive: touch)
}
else {
return false
}
}
@objc func _gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceiveEvent event: UIEvent) -> Bool {
if let navigationController = navigationController, navigationController.isNavigationBarHidden && navigationController.viewControllers.count > 1 {
return true
}
else if let originalDelegate = originalDelegate {
let selector = #selector(_gestureRecognizer(_:shouldReceiveEvent:))
if originalDelegate.responds(to: selector) {
let result = originalDelegate.perform(selector, with: gestureRecognizer, with: event)
return result != nil
}
}
return false
}
override func responds(to aSelector: Selector) -> Bool {
if #available(iOS 13.4, *) {
return originalDelegate?.responds(to: aSelector) ?? false
}
else {
if aSelector == #selector(gestureRecognizer(_:shouldReceive:)) {
return true
}
else {
return originalDelegate?.responds(to: aSelector) ?? false
}
}
}
override func forwardingTarget(for aSelector: Selector) -> Any? {
if #available(iOS 13.4, *), aSelector == #selector(_gestureRecognizer(_:shouldReceiveEvent:)) {
return nil
}
else {
return self.originalDelegate
}
}
}