IOS 13.4 के लिए अपडेट किया गया
iOS 13.4 ने पिछले समाधान को तोड़ दिया, इसलिए चीजें बदसूरत होने वाली हैं। यह iOS 13.4 में दिखता है। यह व्यवहार अब एक निजी विधि द्वारा नियंत्रित किया जाता है _gestureRecognizer:shouldReceiveEvent:
( shouldReceive
iOS 13.4 में जोड़े गए नए सार्वजनिक तरीके से भ्रमित नहीं होना चाहिए )।
मैंने पाया कि अन्य पोस्ट किए गए समाधान प्रतिनिधि को ओवरराइड कर रहे हैं, या इसे शून्य पर सेट करने से कुछ अप्रत्याशित व्यवहार हुआ।
मेरे मामले में, जब मैं नेविगेशन स्टैक के शीर्ष पर था और एक और अधिक पॉप करने के लिए इशारे का उपयोग करने की कोशिश की, तो यह विफल हो जाएगा (जैसा कि अपेक्षित था), लेकिन बाद में स्टैक पर धकेलने के प्रयास अजीब ग्राफिकल ग्लिच का कारण बनने लगेंगे। नेविगेशन बार। यह समझ में आता है, क्योंकि प्रतिनिधि का उपयोग नेविगेशन बार के छिपे होने पर इशारे को पहचाने जाने या न होने से रोकने के लिए अधिक से अधिक संभालने के लिए किया जा रहा है, और अन्य सभी व्यवहार को बाहर किया जा रहा था।
मेरे परीक्षण से, यह प्रतीत होता है कि gestureRecognizer(_:, shouldReceiveTouch:)
यह तरीका है कि मूल प्रतिनिधि इशारे को नेविगेशन बार के छिपे होने पर पहचाने जाने से रोकने के लिए लागू कर रहा है, नहीं gestureRecognizerShouldBegin(_:)
। अन्य समाधान जो gestureRecognizerShouldBegin(_:)
उनके प्रतिनिधि कार्य में लागू होते हैं क्योंकि कार्यान्वयन के अभाव मेंgestureRecognizer(_:, shouldReceiveTouch:)
सभी स्पर्श प्राप्त करने के डिफ़ॉल्ट व्यवहार का कारण होगा।
@ नथन पेरी का समाधान पास हो जाता है, लेकिन कार्यान्वयन के बिना respondsToSelector(_:)
, UIKit कोड जो प्रतिनिधि को संदेश भेजता है, वह विश्वास करेगा कि किसी अन्य प्रतिनिधि विधि के लिए कोई कार्यान्वयन नहीं है, औरforwardingTargetForSelector(_:)
कभी भी कॉल नहीं किया जाएगा।
इसलिए, हम व्यवहार को संशोधित करना चाहते हैं, और अन्यथा प्रतिनिधि को बाकी सभी चीजों को अग्रेषित करना चाहते हैं।
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
}
}
}