IOS 7 पर UINavigationController में बैक स्वाइप जेस्चर को कैसे निष्क्रिय करें


326

IOS 7 में Apple ने एक नया डिफ़ॉल्ट नेविगेशन व्यवहार जोड़ा। आप नेविगेशन स्टैक पर वापस जाने के लिए स्क्रीन के बाएं किनारे से स्वाइप कर सकते हैं। लेकिन मेरे ऐप में, यह व्यवहार मेरे कस्टम बाएं मेनू के साथ संघर्ष करता है। तो, क्या UINavigationController में इस नए इशारे को अक्षम करना संभव है?



2
मुझे यह भी पता चला कि यदि आप सेट करते हैं navigationItem.hidesBackButton = true, तो यह इशारा भी अक्षम हो जाता है। मेरे मामले में मैंने एक कस्टम बैक बटन लागू किया और leftBarButtonItem
उमैर

जवाबों:


586

मुझे एक समाधान मिला:

उद्देश्य सी:

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

स्विफ्ट 3+:
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false


29
बेशक, आपको नए तरीकों की उपलब्धता की जांच करने की आवश्यकता है यदि आप आईओएस के पुराने संस्करणों का समर्थन कर रहे हैं।
आर्टफेल

2
क्या दृश्य की भावना के लिए इसे अक्षम करने का कोई तरीका है?
मार्क

11
आप enable / disableपर पहचान कर सकते हैं viewDidAppear:/ viewDidDisappear। या, आप UIGestureRecognizerDelegateअपने अधिक जटिल तर्क के साथ प्रोटोकॉल को लागू कर सकते हैं और इसे recognizer.delegateसंपत्ति के रूप में सेट कर सकते हैं।
आर्टफेल

26
IOS8 पर, की स्थापना self.navigationController.interactivePopGestureRecognizer.enabledसंपत्ति दृश्य के तरीकों का पालन में काम नहीं करता: viewDidLoad, viewWillAppear, viewDidAppear, viewDidDisappear, लेकिन विधि में काम करता है viewWillDisappear। IOS7 पर यह उपर्युक्त सभी विधियों में काम करता है। इसलिए viewController पर काम करते समय किसी भी अन्य तरीकों से इसका उपयोग करने की कोशिश करें, मैं पुष्टि करता हूं कि यह iOS8 पर मेरे लिए काम करता है जब मैं दृश्य के अंदर कुछ बटन पर क्लिक करता हूं।
सिहद बेगोविक

8
यह पुष्टि कर सकता है कि यह iOS8 में viewDidLoad और viewWillAppear में काम नहीं करेगा, इसे viewwilllayoutgubviews में डालकर चाल
चली

47

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

मेरे लिए फिक्स इशारे को सौंपना था और सं।

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    // Disable iOS 7 back gesture
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.enabled = NO;
        self.navigationController.interactivePopGestureRecognizer.delegate = self;
    }
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    // Enable iOS 7 back gesture
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.enabled = YES;
        self.navigationController.interactivePopGestureRecognizer.delegate = nil;
    }
}

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

1
धन्यवाद! बैक स्वाइप को पूरी तरह से निष्क्रिय करने के लिए यह आवश्यक है। यह अभी भी iOS 8 में मौजूद है, और Apple बग की तरह महक रहा है।
एरिक चेन

धन्यवाद, लगता है कि केवल वही काम किया गया है।
बेन

मैं नहीं जानता कि क्यों, लेकिन किसी अज्ञात कारण से मेरे ऐप में एक व्यू कंट्रोलर इस पीछे के इशारे पर दुर्घटनाग्रस्त हो रहा था .. इससे मुझे इसे खोजने से बचाया क्योंकि मुझे इस बैक जेस्चर की आवश्यकता नहीं थी और इसलिए मैंने इस कोड का उपयोग करके अक्षम कर दिया .. +1
अहसान अब्राहिम

1
@ अहसानबरीम, जब पिछला इशारा शुरू होता है, viewWillAppearवर्तमान दृश्य के पीछे के दृश्य पर कहा जाता है। इससे कोड लॉजिक में तबाही हो सकती है क्योंकि वर्तमान दृश्य अभी भी सक्रिय है। आपके दुर्घटना का कारण हो सकता है।
फातमान

क्या enabledहां / नहीं लाइनों की जरूरत है? आप से लौटते NOहैं gestureRecognizerShouldBegin, यह पर्याप्त नहीं है?
टूलमेकरसेव

30

बस नौवहन पहचानकर्ता को नैविगेशन कंट्रोलर से हटा दें। IOS 8 में काम करते हैं।

if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)])
    [self.navigationController.view removeGestureRecognizer:self.navigationController.interactivePopGestureRecognizer];

एकमात्र समाधान जो वास्तव में ios 8 और 9 में काम करता है
Kappe

7
आईओएस 10 में भी काम करता है, यह स्वीकृत उत्तर होना चाहिए। वैसे, यदि आप इसे फिर से सक्षम करना चाहते हैं, तो [self.navigationController.view addGestureRecognizer:self.navigationController.interactivePopGestureRecognizer]कहीं न कहीं करें।
ओह

22

IOS 8 के रूप में स्वीकृत जवाब अब काम नहीं करता है। मुझे अपने मुख्य खेल स्क्रीन पर इशारे को खारिज करने के लिए सूई को रोकने की जरूरत थी इसलिए इसे लागू किया गया:

- (void)viewDidAppear:(BOOL)animated
{
     [super viewDidAppear:animated];

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

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
    self.navigationController.interactivePopGestureRecognizer.delegate = nil;
    }

}

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

2
हालांकि यह iOS8 के साथ काम करता है मुझे लाइन पर एक चेतावनी मिलती है। बताते हुए: असंगत प्रकार 'ViewController * const __strong' से आईडी <UIGestureRecognizerDelegate> आईडी को असाइन करना
डेविड डगलस

2
IOS8 के रूप में, स्वीकृत उत्तर अभी भी उम्मीद के मुताबिक काम करता है। आप शायद कुछ और गलत कर रहे हैं ..
एलेक्जेंडर जी

यह देखने में स्वीकार किए गए उत्तर को कॉल करके अर्ध काम पाने में सफल रहा। हालाँकि, स्वाइप करने से पृष्ठ 'व्यूडिल्डैड' कहलाने का कारण बनता है, इसलिए फिर से मेरे उत्तर पर वापस लौट आया
चार्ली सेलिगमैन

@DavidDouglas: शायद आप इस कोड के साथ चेतावनी को समाप्त कर सकते हैं: __weak __typeof (self) theSafeSelf = self? फिर प्रतिनिधि को सेटसेफ पर सेट करें।
जीवनज्यो

1
@DavidDouglas: आपको उस चेतावनी से छुटकारा पाने के लिए इंटरफ़ेस में <UIGestureRecognizerDelegate> जोड़ने की जरूरत है
Primehalo

20

मैंने ट्वान के उत्तर को थोड़ा परिष्कृत किया है, क्योंकि:

  1. आपके व्यू कंट्रोलर को अन्य जेस्चर पहचानकर्ताओं के प्रतिनिधि के रूप में सेट किया जा सकता है
  2. के लिए प्रतिनिधि की स्थापना nilके मुद्दों फांसी पर ले जाया जाता है जब आप वापस रूट दृश्य नियंत्रक के पास जाओ और कहीं और नेविगेट करने से पहले एक कड़ी चोट इशारा करते हैं।

निम्न उदाहरण iOS 7 मानता है:

{
    id savedGestureRecognizerDelegate;
}

- (void)viewWillAppear:(BOOL)animated
{
    savedGestureRecognizerDelegate = self.navigationController.interactivePopGestureRecognizer.delegate;
    self.navigationController.interactivePopGestureRecognizer.delegate = self;
}

- (void)viewWillDisappear:(BOOL)animated
{
    self.navigationController.interactivePopGestureRecognizer.delegate = savedGestureRecognizerDelegate;
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    if (gestureRecognizer == self.navigationController.interactivePopGestureRecognizer) {
        return NO;
    }
    // add whatever logic you would otherwise have
    return YES;
}

+1 "प्रतिनिधि को शून्य पर सेट करने से जब आप रूट व्यू कंट्रोलर पर वापस जाते हैं और कहीं और नेविगेट करने से पहले एक स्वाइप जेस्चर बनाते हैं तो वे हैंगिंग मुद्दों की ओर ले जाते हैं।"
अल्बर्टमग

10

कृपया इसे रूट vc में सेट करें:

-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:YES];
    self.navigationController.interactivePopGestureRecognizer.enabled = NO;

}

-(void)viewDidDisappear:(BOOL)animated{
    [super viewDidDisappear:YES];
    self.navigationController.interactivePopGestureRecognizer.enabled = YES;
}

9

स्विफ्ट के लिए:

navigationController!.interactivePopGestureRecognizer!.enabled = false

12
यह काम करता है, हालांकि मैं सुझाव देना चाहूंगा कि बल प्रयोग के बजाय वैकल्पिक चेनिंग का उपयोग करें। उदा। self.navigationController? .interactivePopGestureRecognizer? .isEnabled = false
Womble

5

यह मेरे लिए ios 10 और बाद में काम करता है:

- (void)viewWillAppear:(BOOL)animated {
    if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) {
        self.navigationController.interactivePopGestureRecognizer.enabled = NO;
    }

}

यह viewDidLoad () विधि पर काम नहीं करता है।


5

संपादित करें

यदि आप विशिष्ट नेविगेशन नियंत्रकों के लिए स्वाइप बैक सुविधा का प्रबंधन करना चाहते हैं, तो स्वाइपबैक का उपयोग करने पर विचार करें ।

इसके साथ, आप सेट कर सकते हैं navigationController.swipeBackEnabled = NO

उदाहरण के लिए:

#import <SwipeBack/SwipeBack.h>

- (void)viewWillAppear:(BOOL)animated
{
    navigationController.swipeBackEnabled = NO;
}

इसे CocoaPods के माध्यम से स्थापित किया जा सकता है ।

pod 'SwipeBack', '~> 1.0'

मैं स्पष्टीकरण की कमी के लिए माफी माँगता हूँ।


6
जब आप किसी परियोजना से जुड़े होते हैं, तो उसके साथ अपनी संबद्धता का खुलासा करना चाहिए।

2
इसके अलावा, आपकी परियोजना का एकमात्र उद्देश्य मैन्युअल रूप से स्वाइप जेस्चर को सक्षम करना है जब डिफ़ॉल्ट सिस्टम एक काम नहीं कर रहा है, जबकि सवाल यह पूछता है कि उस सिस्टम को विस्तृत जेस्चर को कैसे अक्षम किया जाए, इसलिए यदि आप सेट करते हैं तो self.navigationController.swipeBackEnabled = NOमुझे पूरा यकीन है कि यह केवल आपके अक्षम कर देगा लाइब्रेरी का स्वाइप बैक जेस्चर है लेकिन सिस्टम अभी भी सक्षम है।

1
मेरे संक्षिप्त उत्तर के लिए क्षमा करें, मैंने अपना उत्तर अतिरिक्त जानकारी के साथ संपादित किया है: "विशिष्ट नेविगेशन नियंत्रकों के लिए उपयोगी"। धन्यवाद!
devxoul

यह स्विज़ल का उपयोग करता प्रतीत होता है जिसे अब अनुमति नहीं है। iOS8?
मैट

1
@devxoul मुझे खेद है! मैंने सोचा था कि मैंने कुछ समय पहले कहा था कि स्विज़लिंग को अब अनुमति नहीं दी गई थी। हालाँकि, मुझे ऐसा कुछ भी नहीं मिला जो यह कहता हो। लगता है कि मैं गलत हूं।
मैट

4

मेरी विधि। उन सभी पर शासन करने के लिए एक इशारा पहचानकर्ता:

class DisabledGestureViewController: UIViewController: UIGestureRecognizerDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        navigationController!.interactivePopGestureRecognizer!.delegate = self
    }

    func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
        // Prevent going back to the previous view
        return !(navigationController!.topViewController is DisabledGestureViewController)
    }
}

महत्वपूर्ण: नेविगेशन स्टैक में कहीं भी प्रतिनिधि को रीसेट न करें: navigationController!.interactivePopGestureRecognizer!.delegate = nil


3

यह स्विफ्ट 3 पर रास्ता है

मेरे लिये कार्य करता है

    self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false

3

ये सभी समाधान ऐप्पल के जेस्चर पहचानकर्ता को एक तरह से हेरफेर करते हैं जो वे अनुशंसा नहीं करते हैं। मुझे सिर्फ एक दोस्त ने बताया है कि एक बेहतर उपाय है:

[navigationController.interactivePopGestureRecognizer requireGestureRecognizerToFail: myPanGestureRecognizer];

जहाँ myPanGestureRecognizer जेस्चर पहचानकर्ता है, जिसका उपयोग आप अपने मेनू को दिखाने के लिए कर रहे हैं। इस तरह, जब आप एक नया नेविगेशन नियंत्रक धक्का देते हैं, तो Apple का जेस्चर पहचानकर्ता उनके द्वारा वापस चालू नहीं होता है और आपको हैकली देरी पर भरोसा करने की आवश्यकता नहीं होती है जो कि आपके फोन को सोने या भारी भार के तहत डालने पर बहुत जल्दी आग लग सकती है।

यहाँ छोड़ना क्योंकि मुझे पता है कि अगली बार जब मुझे इसकी आवश्यकता होगी तो मैं इसे याद नहीं करूँगा, और फिर मेरे पास इस मुद्दे का हल होगा।


3

स्विफ्ट 5, स्विफ्ट 4.2 नीचे दिए गए कोड का उपयोग कर सकता है।

// disable
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
// enable
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = true

2

दिए गए जवाबों में से किसी ने भी इस मुद्दे को हल करने में मेरी मदद नहीं की। मेरे उत्तर को यहाँ पोस्ट करना; किसी के लिए मददगार हो सकता है

private var popGesture: UIGestureRecognizer?अपने दृष्टिकोण में वैश्विक चर के रूप में घोषित करें। फिर viewDidAppear और viewWillDisappear तरीकों में कोड लागू करें

override func viewDidAppear(animated: Bool) {

    super.viewDidAppear(animated)

    if self.navigationController!.respondsToSelector(Selector("interactivePopGestureRecognizer")) {

        self.popGesture = navigationController!.interactivePopGestureRecognizer
        self.navigationController!.view.removeGestureRecognizer(navigationController!.interactivePopGestureRecognizer!)
    }
}


override func viewWillDisappear(animated: Bool) {

    super.viewWillDisappear(animated)

    if self.popGesture != nil {
        navigationController!.view.addGestureRecognizer(self.popGesture!)
    }
}

हो जाएगा ताकि आईओएस में अक्षम कड़ी चोट वापस v8.x बाद


मैं कल्पना करने की कोशिश कर रहा हूं कि यह किन परिस्थितियों में काम करेगा, लेकिन जैक ऐसा नहीं करेगा। आप कहते हैं कि आपने अन्य सभी उत्तरों की कोशिश की: जब आपने जैक की कोशिश की तो क्या गलत हुआ?
ToolmakerSteve

दूसरी ओर, यह जैक की तुलना में सरल लगता है, इसलिए शायद यह महत्वपूर्ण नहीं है। तय किया कि मुझे यह पसंद है, क्योंकि मुझे अपनी कक्षा को एक प्रतिनिधि के रूप में घोषित नहीं करना है, न ही हेरफेर करना है interactivePopGestureRecognizer.delegate
ToolmakerSteve

BTW, कोड को सरल बनाया जा सकता है। हटा दें if( .. respondsToSelector ..। अगली पंक्ति पॉपग्रेस्चर को एक पहचानकर्ता या शून्य पर सेट करती है। फिर इसके मूल्य का उपयोग करें if (self.popGesture != nil) self.navigationController .. removeGestureRecognizer( self.popGesture ):।
टूलमेकरसेव

2

यह viewDidLoad:iOS 8 के लिए काम करता है :

  dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
      self.navigationController.interactivePopGestureRecognizer.enabled = false;
  });

अच्छे ओल की मदद से बहुत सारी समस्याओं को हल किया जा सकता है dispatch_after। '

कृपया ध्यान दें कि यह समाधान संभावित रूप से असुरक्षित है, कृपया अपने स्वयं के तर्क का उपयोग करें।

अपडेट करें

IOS 8.1 के लिए देरी का समय 0.5 सेकंड होना चाहिए

IOS 9.3 पर अब किसी भी देरी की आवश्यकता नहीं है, यह आपके द्वारा बस में काम करता है viewDidLoad:
(TBD अगर iOS 9.0-9.3 पर काम करता है)

navigationController?.interactivePopGestureRecognizer?.enabled = false

जब तक आप यह नहीं जानते कि इशारे पर पहचान करने वाला व्यक्ति कब स्थापित है, तो इसे निष्क्रिय करने के लिए समय की एक मनमानी राशि की प्रतीक्षा करना काम कर सकता है या नहीं।
कलपरिन

@kalperin यह काम करने की गारंटी नहीं है, हालांकि कुछ समय में यह बहुत आसान उपाय है। अपने तर्क का उपयोग करें।
Dannie P

यह मेरे लिए iOS 8.1 :)
iChirag

viewDidLoadप्लस देरी एक जोखिम भरा प्रोग्रामिंग अभ्यास है। शुरुआत करने की बुरी आदत। यदि आपके देरी से कॉल करने से पहले उपयोगकर्ता स्वाइप शुरू करता है तो क्या होगा? ऐसा कोई सुरक्षित समय नहीं है जो लंबे समय तक चलने की गारंटी हो लेकिन अभी बहुत लंबा नहीं है। इसीलिए, आपके द्वारा लंबे समय से पहले पोस्ट किए गए अन्य उत्तर, कोड को अंदर रखने का सुझाव देते हैं viewDidAppear। यह सुनिश्चित करता है कि सब कुछ स्थापित है। मनमाने विलंब का आविष्कार न करें; इरादा के रूप में कॉल के Apple अनुक्रम का उपयोग करें।
टूलमेकरसेव

1
@ आईचराग सच। मैंने नोट किया है कि 8.1 के लिए आपको 0.5 सेकंड की देरी की आवश्यकता है
Dannie P

1

के लिए स्विफ्ट 4 यह काम करता है:

class MyViewController: UIViewController, UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

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

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

        self.navigationController?.interactivePopGestureRecognizer?.gesture.isEnabled = false
    }

}

आपको इंटरेक्टिव पॉप जेस्चर डेलीगेट को ओवरराइड नहीं करना चाहिए क्योंकि इससे
अनैच्छिक

मुझे लगता है कि यह वास्तव में प्रतिनिधि को ओवरराइड नहीं कर रहा है, लेकिन सिर्फ बूलियन चर को संशोधित कर रहा है जो उन्होंने इस उद्देश्य के लिए प्रदान किया है, इसलिए यह एक समस्या नहीं होगी
लोक एसएन

0

इसने मेरे लिए अधिकतर दर्शकों के लिए काम किया।

self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false

यह UIPageViewController जैसे कुछ देखने के लिए काम नहीं कर रहा था। कोड के नीचे UIPageViewController के पेज कॉन्टेंटव्यूकंट्रोलर ने मेरे लिए काम किया।

override func viewDidLoad() {
   self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
   self.navigationController?.interactivePopGestureRecognizer?.delegate = self
}
override func viewWillDisappear(_ animated: Bool) {
   self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
   self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
}

UIGestureRecognizerDelegate पर,

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
   if gestureRecognizer == self.navigationController?.interactivePopGestureRecognizer {
      return false
}
      return true
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.