UINavigationController में नेविगेशन बार छिपाते समय कोई स्वाइप बैक नहीं


86

मुझे स्वाइप पैक से प्यार है जो आपके विचारों को एक में एम्बेड करने से विरासत में मिला है UINavigationController। दुर्भाग्य से मैं छुपाने का कोई तरीका नहीं खोज सकता NavigationBarलेकिन फिर भी टच पैन स्वाइप बैक है gesture। मैं कस्टम इशारों को लिख सकता हूं, लेकिन मैं इसके बजाय UINavigationControllerपीछे के स्वाइप पर भरोसा नहीं करना चाहता हूं gesture

अगर मैं इसे स्टोरीबोर्ड में अनचेक करता हूं, तो बैक स्वाइप काम नहीं करता है

यहाँ छवि विवरण दर्ज करें

वैकल्पिक रूप से अगर मैं प्रोग्रामेटिक रूप से इसे छुपाता हूं, तो यही परिदृश्य।

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.navigationController setNavigationBarHidden:YES animated:NO]; // and animated:YES
}

क्या शीर्ष को छिपाने का कोई तरीका नहीं है NavigationBarऔर अभी भी स्वाइप है?


1
क्या UIGestureRecognizer जोड़ना स्वीकार्य है? यह लागू करने के लिए एक हवा है।
स्विफ्टआर्किटेक्ट

1
@ LancelotdelaMare, मैं इससे बचने की कोशिश कर रहा था क्योंकि यह UINavigationController वापस स्वाइप के रूप में आसानी से काम नहीं करेगा। Im UIScreenEdgePanGestureRecognizer में देख रहा है क्योंकि कुछ लोग कहते हैं कि यह मदद करता है लेकिन अभी तक काम करने के लिए इसे प्राप्त नहीं किया है। सबसे सरल और सबसे सुरुचिपूर्ण समाधान की तलाश में यहां।
मिहाई

जवाबों:


96

एक हैक है कि काम कर रहा है स्थापित करने के लिए है interactivePopGestureRecognizerकी के प्रतिनिधि UINavigationControllerको nilइस तरह:

[self.navigationController.interactivePopGestureRecognizer setDelegate:nil];

लेकिन कुछ स्थितियों में यह अजीब प्रभाव पैदा कर सकता है।


16
"बार-बार स्वाइप करने से हावभाव को पहचाना जा सकता है जब स्टैक पर केवल एक व्यू कंट्रोलर होता है, जो बदले में एक यूआई डालता है (मुझे UIKit इंजीनियरों द्वारा अप्रत्याशित लगता है) राज्य जहां यह किसी भी इशारों को पहचानना बंद कर देता है"
हॉर्स टीटी

4
एक वैकल्पिक कि कि अप्रत्याशित राज्य के खिलाफ की रक्षा कर सकते हैं (मैं अपने ऐप प्रतिनिधि थे) कुछ निम्न स्तर वस्तु के लिए सेट और लागू करने के लिए किया जाएगा gestureRecognizerShouldBegin, लौटने trueअगर navigationControllerकी viewControllerगिनती से अधिक है 0.
केनी Winker

4
हालांकि यह काम करता है, मैं इसके खिलाफ अत्यधिक सलाह देता हूं। प्रतिनिधि को तोड़ना मुख्य थ्रेड ब्लॉक की पहचान करने के लिए एक दुर्लभ और कठिन कारण था। यह एक मुख्य थ्रेड ब्लॉक नहीं है, लेकिन इसकी @HorseT वर्णित है।
जोश बर्नफेल्ड

3
मेरा ऐप प्रतिनिधि प्रतिनिधि को बचाता है और फिर इसे पुनर्स्थापित करता है viewWillDisappearऔर अब तक प्रतिकूल दुष्प्रभावों का अनुभव नहीं किया है।
डॉन पार्क

1
!!!! इस समाधान का उपयोग करने के लिए अत्यधिक हतोत्साहित करें, जब बार-बार एक अजीब व्यवहार का उपयोग करते हुए स्वाइप होता है, तो बैक अक्षम होता है और संपूर्ण ऐप किसी भी अधिक प्रतिक्रिया नहीं देता है
करीमहब

79

अन्य विधियों के साथ समस्या

interactivePopGestureRecognizer.delegate = nilअनपेक्षित साइड-इफेक्ट्स सेट करना ।

सेटिंग navigationController?.navigationBar.hidden = trueकाम करती है, लेकिन नेविगेशन बार में आपके परिवर्तन को छिपाने की अनुमति नहीं देती है।

अंत में, यह आमतौर पर एक मॉडल ऑब्जेक्ट बनाने के लिए बेहतर अभ्यास है जो UIGestureRecognizerDelegateआपके नेविगेशन नियंत्रक के लिए है। UINavigationControllerस्टैक में एक नियंत्रक पर सेट करना EXC_BAD_ACCESSत्रुटियों का कारण है ।

पूर्ण समाधान

सबसे पहले, इस वर्ग को अपनी परियोजना में जोड़ें:

class InteractivePopRecognizer: NSObject, UIGestureRecognizerDelegate {

    var navigationController: UINavigationController

    init(controller: UINavigationController) {
        self.navigationController = controller
    }

    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return navigationController.viewControllers.count > 1
    }

    // This is necessary because without it, subviews of your top controller can
    // cancel out your gesture recognizer on the edge.
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

फिर, अपने नेविगेशन नियंत्रक interactivePopGestureRecognizer.delegateको अपने नए InteractivePopRecognizerवर्ग के उदाहरण में सेट करें ।

var popRecognizer: InteractivePopRecognizer?

override func viewDidLoad() {
    super.viewDidLoad()
    setInteractiveRecognizer()
}

private func setInteractiveRecognizer() {
    guard let controller = navigationController else { return }
    popRecognizer = InteractivePopRecognizer(controller: controller)
    controller.interactivePopGestureRecognizer?.delegate = popRecognizer
}

बिना किसी साइड इफेक्ट के साथ एक छिपी हुई नेविगेशन बार का आनंद लें, यह तब भी काम करता है, जब आपके टॉप कंट्रोलर के पास टेबल, कलेक्शन, या व्यू सबव्यू हो।


1
महान समाधान!
मैट बटलर

1
सबसे अच्छा जवाब, धन्यवाद!
डोरियल डैनियल

2
@HunterMaximillionMonk महान समाधान के लिए धन्यवाद। यह एक आकर्षण की तरह काम करता है
diu

1
@HunterMaximillionMonk ऐसा लगता है कि सही ढंग से काम करता है, लेकिन इसके साथ समस्या है जब मेरे पास कई नियंत्रक हैं तो एक समय के बाद पॉप काम करना बंद कर देता है।
प्रेमल खेतानी

1
निश्चित रूप से सबसे अच्छा जवाब!
daxh

54

मेरे मामले में, अजीब प्रभावों को रोकने के लिए

रूट व्यू कंट्रोलर

override func viewDidLoad() {
    super.viewDidLoad()

    // Enable swipe back when no navigation bar
    navigationController?.interactivePopGestureRecognizer?.delegate = self 

}


func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
    if(navigationController!.viewControllers.count > 1){
        return true
    }
    return false
}

http://www.gampood.com/pop-viewcontroller-with-out-navigation-bar/


2
कभी-कभी इसका उपयोग करते समय मुझे EXC_BAD_ACCESS हो रहा है
एंड्री गोर्डीव

मेरे लिए, यह इशारा काम नहीं करता है और अक्सर EXEC_BAD_ACCESS
बेंजो सिप

2
UIGestureRecognizerDelegateरूट व्यू कंट्रोलर में जोड़ने के लिए याद रखें ... मेरे मामले में प्रतिनिधि को रूट व्यू कंट्रोलर की तुलना में बाद के व्यू कंट्रोलर में शून्य करने के लिए सेट किया गया था, इसलिए जब रूट व्यू कंट्रोलर को लौटाया गया, तो gestureRecognizerShouldBeginउसे कॉल नहीं किया गया। तो मैं रखा .delegate = selfमें viewDidAppear()। कि मेरे मामले में अजीब प्रभाव को हल किया .. चीयर्स!
14

@AndreyGordeev क्या होने के बारे में कुछ जानकारी दे सकते हैं EXEC_BAD_ACCESS?
Jaybo

यहाँ EXC_BAD_ACCESSत्रुटि के बारे में अधिक जानकारी है : stackoverflow.com/questions/28746123/…
एंड्री गोर्डीव

25

IOS 13.4 के लिए अपडेट किया गया

iOS 13.4 ने पिछले समाधान को तोड़ दिया, इसलिए चीजें बदसूरत होने वाली हैं। यह iOS 13.4 में दिखता है। यह व्यवहार अब एक निजी विधि द्वारा नियंत्रित किया जाता है _gestureRecognizer:shouldReceiveEvent:( shouldReceiveiOS 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
    }

    // For handling iOS before 13.4
    @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
        }
    }

    // For handling iOS 13.4+
    @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, *) {
            // iOS 13.4+ does not need to override responds(to:) behavior, it only uses forwardingTarget
            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
        }
    }
}

1
लगता है कि इस पल के लिए आपका समाधान सबसे अच्छा है। धन्यवाद!
तैमूर बर्निकोविच

"लेकिन बाद में स्टैक पर धकेलने का प्रयास नेविगेशन बार में अजीब ग्राफिकल ग्लिच का कारण बनने लगेगा" - मैं यहाँ उलझन में हूँ। मुझे लगा कि हमारे पास कोई नेविगेशन बार नहीं है? यही तो प्रश्न है? मेरी स्थिति में, मेरे पास एक नेविगेशन कंट्रोलर है जो बिना किसी नौसिखिए के साथ चाइल्ड व्यू कंट्रोलर के रूप में एम्बेडेड है; युक्त VC में नेविगेशन नियंत्रण हैं। तो मैंने युक्त वीसी को पहचानकर्ता का प्रतिनिधि होने दिया और बस काम किया gestureRecognizerShouldBegin:, और यह "काम करने लगता है"। सोच रहा था कि मुझे बाहर देखना चाहिए।
अगस्त को

2
navigationControllerऑलवेजपॉपेबलडेलेगेट में एक मजबूत संदर्भ के बाद से यह एक स्मृति रिसाव था। मैंने इसे एक weakसंदर्भ बनाने के लिए कोड को संपादित किया है ।
ग्राहम पर्क्स

3
आईओएस 13.4 में यह अच्छा समाधान अब काम नहीं करता है
एली

@CrrisVasselli वास्तव में बहुत बढ़िया, धन्यवाद! उम्मीद है कि यह ऐप स्टोर की समीक्षा के निजी तरीकों की जाँच करेगा।
एली

16

आप निम्न के रूप में UINavigationController उप-वर्ग कर सकते हैं:

@interface CustomNavigationController : UINavigationController<UIGestureRecognizerDelegate>

@end

कार्यान्वयन:

@implementation CustomNavigationController

- (void)setNavigationBarHidden:(BOOL)hidden animated:(BOOL)animated {
    [super setNavigationBarHidden:hidden animated:animated];
    self.interactivePopGestureRecognizer.delegate = self;
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if (self.viewControllers.count > 1) {
        return YES;
    }
    return NO;
}

@end

2
इस दृष्टिकोण का उपयोग UIPageViewControllerओवरस्क्रॉल में पॉप इशारे को तोड़ रहा है ।
अतुलखत्री

मैंने पाया कि viewController.count> 1 चेक आवश्यक है। यदि उपयोगकर्ता केवल मूल VC के साथ वापस स्वाइप करने का प्रयास करता है, तो UI अगले VC पुश पर लटका होगा।
वेपरवेयरवॉल्फ

11

सरल, कोई साइड-इफेक्ट उत्तर नहीं

जबकि यहां अधिकांश उत्तर अच्छे हैं, वे प्रतीत होता है कि अनपेक्षित रूप से दुष्प्रभाव (ऐप ब्रेकिंग) या क्रिया हैं।

सबसे सरल अभी तक कार्यात्मक समाधान के साथ मैं आ सकता है निम्नलिखित था:

ViewController में है कि आप नेविगेशन को छिपा रहे हैं,

class MyNoNavBarViewController: UIViewController {
    
    // needed for reference when leaving this view controller
    var initialInteractivePopGestureRecognizerDelegate: UIGestureRecognizerDelegate?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // we will need a reference to the initial delegate so that when we push or pop.. 
        // ..this view controller we can appropriately assign back the original delegate
        initialInteractivePopGestureRecognizerDelegate = self.navigationController?.interactivePopGestureRecognizer?.delegate
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(true)

        // we must set the delegate to nil whether we are popping or pushing to..
        // ..this view controller, thus we set it in viewWillAppear()
        self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(true)

        // and every time we leave this view controller we must set the delegate back..
        // ..to what it was originally
        self.navigationController?.interactivePopGestureRecognizer?.delegate = initialInteractivePopGestureRecognizerDelegate
    }
}

अन्य जवाबों ने केवल प्रतिनिधि को शून्य करने के लिए सुझाव दिया है। नेविगेशन स्टैक पर प्रारंभिक दृश्य नियंत्रक को पीछे की ओर स्वाइप करने से सभी इशारे अक्षम हो जाते हैं। कुछ प्रकार के, शायद, UIKit / UIGesture देवों के।

साथ ही, कुछ उत्तर जो मैंने यहां लागू किए हैं, उनके परिणामस्वरूप गैर-मानक ऐप्पल नेविगेशन व्यवहार (विशेष रूप से, पीछे की ओर स्वाइप करते समय ऊपर या नीचे स्क्रॉल करने की क्षमता के लिए अनुमति देता है)। ये जवाब भी थोड़ा सा लगता है और कुछ मामलों में अधूरा है।


viewDidLoad()कब्जा करने के लिए एक अच्छी जगह नहीं है initialInteractivePopGestureRecognizerDelegateक्योंकि navigationControllerवहाँ शून्य हो सकता है (स्टैक पर अभी तक नहीं धकेल दिया गया)। viewWillAppearउस स्थान पर जहाँ आप नेविगेशन बार छुपा रहे हैं, अधिक उपयुक्त होगा
nCod3d

10

के बंद का निर्माण हंटर Maximillion भिक्षु के जवाब , मैं UINavigationController के लिए एक उपवर्ग बनाया और फिर मेरी स्टोरीबोर्ड में मेरी UINavigationController के लिए कस्टम वर्ग निर्धारित किया है। दो वर्गों के लिए अंतिम कोड इस तरह दिखता है:

InteractivePopRecognizer:

class InteractivePopRecognizer: NSObject {

    // MARK: - Properties

    fileprivate weak var navigationController: UINavigationController?

    // MARK: - Init

    init(controller: UINavigationController) {
        self.navigationController = controller

        super.init()

        self.navigationController?.interactivePopGestureRecognizer?.delegate = self
    }
}

extension InteractivePopRecognizer: UIGestureRecognizerDelegate {
    func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return (navigationController?.viewControllers.count ?? 0) > 1
    }

    // This is necessary because without it, subviews of your top controller can cancel out your gesture recognizer on the edge.
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

HiddenNavBarNavigationController:

class HiddenNavBarNavigationController: UINavigationController {

    // MARK: - Properties

    private var popRecognizer: InteractivePopRecognizer?

    // MARK: - Lifecycle

    override func viewDidLoad() {
        super.viewDidLoad()
        setupPopRecognizer()
    }

    // MARK: - Setup

    private func setupPopRecognizer() {
        popRecognizer = InteractivePopRecognizer(controller: self)
    }
}

स्टोरीबोर्ड:

स्टोरीबोर्ड नव नियंत्रक कस्टम वर्ग


8

@ChrisVasseli द्वारा प्रदान किया गया समाधान सबसे अच्छा लगता है। मैं उद्देश्य-सी में एक ही समाधान प्रदान करना चाहता हूं क्योंकि प्रश्न उद्देश्य-सी के बारे में है (टैग देखें)

@interface InteractivePopGestureDelegate : NSObject <UIGestureRecognizerDelegate>

@property (nonatomic, weak) UINavigationController *navigationController;
@property (nonatomic, weak) id<UIGestureRecognizerDelegate> originalDelegate;

@end

@implementation InteractivePopGestureDelegate

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    if (self.navigationController.navigationBarHidden && self.navigationController.viewControllers.count > 1) {
        return YES;
    } else {
        return [self.originalDelegate gestureRecognizer:gestureRecognizer shouldReceiveTouch:touch];
    }
}

- (BOOL)respondsToSelector:(SEL)aSelector
{
    if (aSelector == @selector(gestureRecognizer:shouldReceiveTouch:)) {
        return YES;
    } else {
        return [self.originalDelegate respondsToSelector:aSelector];
    }
}

- (id)forwardingTargetForSelector:(SEL)aSelector
{
    return self.originalDelegate;
}

@end

@interface NavigationController ()

@property (nonatomic) InteractivePopGestureDelegate *interactivePopGestureDelegate;

@end

@implementation NavigationController

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.interactivePopGestureDelegate = [InteractivePopGestureDelegate new];
    self.interactivePopGestureDelegate.navigationController = self;
    self.interactivePopGestureDelegate.originalDelegate = self.interactivePopGestureRecognizer.delegate;
    self.interactivePopGestureRecognizer.delegate = self.interactivePopGestureDelegate;
}

@end

3
क्योंकि ओबीजीसी अभी मरा नहीं है! 😉
महाशय

2
यह सही उपाय है। कोई अन्य समाधान जो मूल प्रतिनिधि को अग्रेषित नहीं करता है वह गलत है।
जोश बर्नफेल्ड

6

मेरा समाधान सीधे UINavigationControllerवर्ग का विस्तार करना है :

import UIKit

extension UINavigationController: UIGestureRecognizerDelegate {

    override open func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)

        self.interactivePopGestureRecognizer?.delegate = self
    }

    public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
        return self.viewControllers.count > 1
    }

}

इस तरह, सभी नेविगेशन कंट्रोलर स्लाइडिंग द्वारा खारिज करने योग्य होंगे।


विचित्र रूप से यह पर्याप्त है viewDidAppearकि किसी भी नेविगेशन नियंत्रक से संबंधित कुलपतियों की सभी कॉलों को अनदेखा किया जा रहा है।
सहकर्मी

4

आप इसे एक प्रॉक्सी डेलीगेट के साथ कर सकते हैं। जब आप नेविगेशन नियंत्रक का निर्माण कर रहे हों, तो मौजूदा प्रतिनिधि को पकड़ लें। और इसे प्रॉक्सी में पास करें। फिर मौजूदा प्रतिनिधि को gestureRecognizer:shouldReceiveTouch:उपयोग करने के अलावा सभी प्रतिनिधि विधियों को पास करेंforwardingTargetForSelector:

सेट अप:

let vc = UIViewController(nibName: nil, bundle: nil)
let navVC = UINavigationController(rootViewController: vc)
let bridgingDelegate = ProxyDelegate()
bridgingDelegate.existingDelegate = navVC.interactivePopGestureRecognizer?.delegate
navVC.interactivePopGestureRecognizer?.delegate = bridgingDelegate

प्रॉक्सी प्रतिनिधि:

class ProxyDelegate: NSObject, UIGestureRecognizerDelegate {
    var existingDelegate: UIGestureRecognizerDelegate? = nil

    override func forwardingTargetForSelector(aSelector: Selector) -> AnyObject? {
        return existingDelegate
    }

    func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
        return true
    }  
}

यह जवाब सच है ओब्ज-सी शैली!
साउंड ब्लास्टर

अग्रेषणटार्गफॉरसेलेटर ने मुझे एक पिछली परियोजना पर इतना समय बचाया होगा, जिसके बारे में मुझे पता था। अच्छी चीज़!
वेपरवेयरवॉल्फ

4

हंटर मोंक का जवाब वास्तव में भयानक है, लेकिन दुर्भाग्य से iOS 13.3.1 में, यह काम नहीं करता है।

मैं छुपाने UINavigationBarऔर न हारने का दूसरा तरीका बताऊंगा swipe to back gesture। मैंने iOS 13.3.1 और 12.4.3 पर परीक्षण किया है और यह काम करता है।

आप के लिए एक कस्टम वर्ग बनाने UINavigationControllerऔर उस वर्ग को सेट करने की आवश्यकता UINavigationControllerहैStoryboard

कस्टम क्लास को <code> UINavigationController </ code> पर सेट करें

NavigationBarपर छिपा नहीं हैStoryboard

<कोड> UINavigationController </ कोड> निरीक्षक विशेषताएँ:

पर उदाहरण Storyboard:

स्टोरीबोर्ड:

और अंत में, यह डाल: navigationBar.isHidden = trueमें viewDidLoadकी CustomNavigationControllerकक्षा।

सुनिश्चित करें, इस पद्धति का उपयोग setNavigationBarHidden(true, animated: true)छुपाने के लिए न करें NavigationBar

import UIKit

class CustomNavigationController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationBar.isHidden = true
    }
}

2
मैंने असली डिवाइस iPhone 6S Plus के साथ इसका परीक्षण किया है iOS 13.4.1और वापस काम करता है।
इमरे आयदिन

1
नए iOS 14.0.1
बेजोदम

1

Xamarin उत्तर:

IUIGestureRecognizerDelegateअपने ViewController की कक्षा परिभाषा में इंटरफ़ेस को लागू करें :

public partial class myViewController : UIViewController, IUIGestureRecognizerDelegate

अपने ViewController में निम्नलिखित विधि जोड़ें:

[Export("gestureRecognizerShouldBegin:")]
public bool ShouldBegin(UIGestureRecognizer recognizer) {
  if (recognizer is UIScreenEdgePanGestureRecognizer && 
      NavigationController.ViewControllers.Length == 1) {
    return false;
  }
  return true;
}

अपने ViewController ViewDidLoad()में निम्न पंक्ति जोड़ें:

NavigationController.InteractivePopGestureRecognizer.Delegate = this;

संभवतः यह UINavigationControllerरूट व्यू कंट्रोलर में है? EXEC_BAD_ACCESSजब मैं यह कोशिश करता हूं तो मुझे मिलता है ।
बेंजोना

आप मूल दृश्य नियंत्रक पर पैन को किनारे करने में सक्षम हैं? यह संभव नहीं होना चाहिए क्योंकि जब आप रूट वीसी पर होते हैं तो आपने अन्य सभी वीसी को पॉपअप कर दिया होता है, और आपके एनवी के वीसी एरे की लंबाई 1. होनी चाहिए।
अहमद

कॉल करने से पहले क्रैश होता है gestureRecognizerShouldBegin:
बेंजामिन

1
क्या आप अपने वीसी कोड को एक नए प्रश्न में या ज़मारिन मंचों पर पोस्ट कर सकते हैं?
अहमद

नहीं, मैंने नहीं। मुझे लगता है कि मैं इसे छोड़ दूंगा!
बेंजॉन

1

मैंने यह कोशिश की है और यह पूरी तरह से काम कर रहा है: स्लाइड-बैक क्षमता खोए बिना नेविगेशन बार को कैसे छिपाएं

विचार अपने .h में "UIGestureRecognizerDelegate" को लागू करना है और इसे अपनी फ़ाइल में जोड़ना है।

- (void)viewWillAppear:(BOOL)animated {
// hide nav bar
[[self navigationController] setNavigationBarHidden:YES animated:YES];

// enable slide-back
if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
    self.navigationController.interactivePopGestureRecognizer.enabled = YES;
    self.navigationController.interactivePopGestureRecognizer.delegate = self;
  }
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
   return YES;  
}

1

यहां मेरा समाधान है: मैं नेविगेशन बार पर अल्फा बदल रहा हूं, लेकिन नेविगेशन बार छिपा नहीं है। मेरे सभी दृश्य नियंत्रक मेरे BaseViewController का एक उपवर्ग हैं, और वहां मेरे पास हैं:

    override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    navigationController?.navigationBar.alpha = 0.0
}

आप UINavigationController को भी उपवर्गित कर सकते हैं और उस पद्धति को वहां रख सकते हैं।


0

कुछ लोगों को इसके बजाय setNavigationBarHiddenएनिमेटेड विधि के साथ कॉल करके सफलता मिली है YES


मैंने कोई भाग्य नहीं आजमाया। इस सुझाव को कवर करने के लिए मेरे उत्तर को अपडेट करना।
मिहाई

0

नेविगेशनबार के बिना मेरे विचार नियंत्रक में मैं उपयोग करता हूं

open override func viewWillAppear(_ animated: Bool) {
  super.viewWillAppear(animated)

  CATransaction.begin()
  UIView.animate(withDuration: 0.25, animations: { [weak self] in
    self?.navigationController?.navigationBar.alpha = 0.01
  })
  CATransaction.commit()
}

open override func viewWillDisappear(_ animated: Bool) {
  super.viewWillDisappear(animated)
  CATransaction.begin()
  UIView.animate(withDuration: 0.25, animations: { [weak self] in
    self?.navigationController?.navigationBar.alpha = 1.0
  })
  CATransaction.commit()
}

इंटरएक्टिव बर्खास्तगी के दौरान बैक बटन हालांकि चमक जाएगा, यही कारण है कि मैंने इसे छिपा दिया।


-2

वहाँ एक बहुत ही सरल उपाय है जो मैंने कोशिश की और पूरी तरह से काम करता है, यह Xamarin.iOS में है लेकिन मूल के लिए भी लागू किया जा सकता है:

    public override void ViewWillAppear(bool animated)
    {
        base.ViewWillAppear(animated);
        this.NavigationController.SetNavigationBarHidden(true, true);
    }

    public override void ViewDidAppear(bool animated)
    {
        base.ViewDidAppear(animated);
        this.NavigationController.SetNavigationBarHidden(false, false);
        this.NavigationController.NavigationBar.Hidden = true;
    }

    public override void ViewWillDisappear(bool animated)
    {
        base.ViewWillDisappear(animated);
        this.NavigationController.SetNavigationBarHidden(true, false);
    }

-6

जब उपयोगकर्ता ViewController से बाहर स्लाइड करता है तो यहां डि जेस्चर पहचानकर्ता को अक्षम कैसे किया जाए। आप इसे अपने viewWillAppear () या अपने ViewDidLoad () विधियों पर पेस्ट कर सकते हैं।

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
    self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}

उत्तर पोस्ट करने से पहले कृपया प्रश्न पढ़ें। प्रश्न इसे सक्षम करने के बारे में था, इसे अक्षम करने में नहीं। हम पीओपी इशारे से प्यार करते हैं।
योगेश माहेश्वरी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.