अगर किसी व्यू कंट्रोलर को मामूली रूप से प्रस्तुत किया जाता है या नेविगेशन स्टैक पर धकेल दिया जाता है तो कैसे जांच करें?


126

मैं अपने व्यू कंट्रोलर कोड में कैसे अंतर कर सकता हूं:

  • औपचारिक रूप से प्रस्तुत किया
  • नेविगेशन स्टैक पर धक्का दिया

दोनों presentingViewControllerऔर isMovingToParentViewControllerहैंYES दोनों ही मामलों में, तो बहुत उपयोगी नहीं हैं।

जो चीजें उलझी हुई हैं, वह यह है कि मेरे पैरेंट व्यू कंट्रोलर कभी-कभी मोडल होते हैं, जिस पर चेक किए जाने वाले व्यू कंट्रोलर को धक्का दिया जाता है।

यह पता चला है कि मेरा मुद्दा यह है कि मैं HtmlViewControllerएक में UINavigationControllerप्रस्तुत किया है जो तब एम्बेड मेरी । इसलिए मेरे अपने प्रयास और नीचे दिए गए अच्छे जवाब काम नहीं कर रहे थे।

HtmlViewController*     termsViewController = [[HtmlViewController alloc] initWithDictionary:dictionary];
UINavigationController* modalViewController;

modalViewController = [[UINavigationController alloc] initWithRootViewController:termsViewController];
modalViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:modalViewController
                   animated:YES
                 completion:nil];

मुझे लगता है कि मैं अपने दृश्य नियंत्रक को बेहतर बताऊंगा जब यह निर्धारित करने की कोशिश करने के बजाय मोडल हो।

जवाबों:


125

नमक के एक दाने के साथ ले लो, परीक्षण नहीं किया।

- (BOOL)isModal {
     if([self presentingViewController])
         return YES;
     if([[[self navigationController] presentingViewController] presentedViewController] == [self navigationController])
         return YES;
     if([[[self tabBarController] presentingViewController] isKindOfClass:[UITabBarController class]])
         return YES;

    return NO;
 }

12
मुझे यह एक और एसओ पोस्ट में मिला। लेकिन, काम नहीं करता है अगर धक्का दिया गया दृश्य नियंत्रक का माता-पिता एक मॉडल है; जो स्थिति मैं कर रहा हूँ।
अर्थ-मायने

2
जैसा कि मैंने लिखा है, presentingViewControllerहमेशा YESमेरे मामले में है; सहायता नहीं करता है।
अर्थ-मायने

3
presentingViewControllerYESजब UITabBarControllerकोई मूल के रूप में सेट किया जा रहा है, तो धकेल दिए गए कुलपति के लिए रिटर्न । इसलिए, मेरे मामले में उपयुक्त नहीं है।
येवैन दुबीनिन

5
यह काम नहीं करता है यदि आप एक दृश्य नियंत्रक प्रस्तुत करते हैं तो यह एक और धक्का देता है।
ली

3
"यह काम नहीं करता है यदि आप एक दृश्य नियंत्रक प्रस्तुत करते हैं तो यह एक और एक धक्का देता है" यही इसका उद्देश्य नहीं है, धक्का दिया गया दृश्य नियंत्रक प्रस्तुत नहीं किया जा रहा है।
कॉलिन स्वेलिन

87

में स्विफ्ट :

यह परीक्षण करने के लिए एक ध्वज जोड़ें कि क्या यह वर्ग प्रकार द्वारा एक मोडल है:

// MARK: - UIViewController implementation

extension UIViewController {

    var isModal: Bool {

        let presentingIsModal = presentingViewController != nil
        let presentingIsNavigation = navigationController?.presentingViewController?.presentedViewController == navigationController
        let presentingIsTabBar = tabBarController?.presentingViewController is UITabBarController

        return presentingIsModal || presentingIsNavigation || presentingIsTabBar
    }
}

4
एक var isModal: Bool {}
संस्करण

1
@ कमाल को बदल दिया जाता है
यैनस्टेफ़

कथन falseमें अंतिम पैरामीटर returnक्या है?
दमजंद

? आप यह बताने के लिए presentingIsNavigation = navigationController .presentingViewController .presentedViewController == navigationController && navigationController बदलने की जरूरत = शून्य!
FamFamFam

78

आपने एक विधि की अनदेखी की isBeingPresented:।

isBeingPresented सही है जब दृश्य नियंत्रक प्रस्तुत किया जा रहा है और धक्का दिए जाने पर गलत है।

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

    if ([self isBeingPresented]) {
        // being presented
    } else if ([self isMovingToParentViewController]) {
        // being pushed
    } else {
        // simply showing again because another VC was dismissed
    }
}

2
मैंने पोस्ट करने से पहले भी यह कोशिश की, और यह काम नहीं करता है, isBeingPresentedहै NO। लेकिन मैं अब कारण देख रहा हूं, मैं अपने प्रस्तुत दृश्य नियंत्रक को एक में एम्बेड कर रहा हूं UINavigationController, और वह वह है जिसे मैं धक्का दे रहा हूं।
अर्थ-मायने

1
आप एक नेविगेशन नियंत्रक को धक्का नहीं दे सकते। शायद आपका मतलब था कि आप नेविगेशन नियंत्रक को प्रस्तुत कर रहे हैं।
rmaddy

3
@jowie उपयोग p, नहीं poजब एक आदिम मूल्य मुद्रण। poवस्तुओं की छपाई के लिए है।
14

37
के लिए दस्तावेज़ीकरण isBeingPresented- यह विधि केवल तभी वापस आती है जब व्यू व्यू के अंदर से कॉल की जाती है: और व्यूडाईपर: तरीके।
फंक्शनल 7

4
@ यह लगता है कि नवीनतम दस्तावेज़ उस जानकारी को नहीं दिखाते हैं लेकिन यह वहाँ हुआ करता था। isBeingPresented, isBeingDismissed, isMovingFromParentViewControllerऔर isMovingToParentViewController4 के अंदर ही मान्य हैं view[Will|Did][Disa|A]ppearतरीकों।
रामादेवी

29

स्विफ्ट 5
यहां वह समाधान है जो पिछले उत्तरों के साथ उल्लिखित मुद्दे को संबोधित करता है, जब isModal()रिटर्न एक trueधक्का दिया UIViewControllerजाता है UINavigationController

extension UIViewController {
    var isModal: Bool {
        if let index = navigationController?.viewControllers.firstIndex(of: self), index > 0 {
            return false
        } else if presentingViewController != nil {
            return true
        } else if navigationController?.presentingViewController?.presentedViewController == navigationController {
            return true
        } else if tabBarController?.presentingViewController is UITabBarController {
            return true
        } else {
            return false
        }
    }
}

यह मेरे लिए अब तक का काम है। अगर कुछ अनुकूलन, कृपया साझा करें।


आपको जांच करने की आवश्यकता क्यों है tabBarController?.presentingViewController is UITabBarController ? क्या यह मायने रखता है अगर वह presentingViewControllerभी UITabBarController है?
२१:४० बजे ह्लंग

और अगर नेविगेशनकंट्रोलर शून्य है, isModalतो वापस आ जाएगा true। क्या यह इरादा है?
7

28

self.navigationController! = nil का मतलब होगा कि यह एक नेविगेशन स्टैक में है।

इस मामले को संभालने के लिए कि वर्तमान दृश्य नियंत्रक को धक्का दिया जाता है जबकि नेविगेशन नियंत्रक को मामूली रूप से प्रस्तुत किया जाता है, मैंने यह जांचने के लिए कोड की कुछ पंक्तियों को जोड़ा है कि क्या वर्तमान दृश्य नियंत्रक नेविगेशन स्टैक में रूट नियंत्रक है।

extension UIViewController {
    var isModal: Bool {
        if let index = navigationController?.viewControllers.firstIndex(of: self), index > 0 {
            return false
        } else if presentingViewController != nil {
            return true
        } else if let navigationController = navigationController, navigationController.presentingViewController?.presentedViewController == navigationController {
            return true
        } else if let tabBarController = tabBarController, tabBarController.presentingViewController is UITabBarController {
            return true
        } else {
            return false
        }
    }
}

आम तौर पर जब आप सामान्य रूप से पेश करते हैं, तो आप एक नेविगेशनकंट्रोलर पर viewController डालते हैं और आप इसे प्रस्तुत करते हैं। अगर ऐसा है तो आपका बयान गलत होगा, हालांकि कोड पर इस मामले को संभाला जाता है। कृपया अपना उत्तर
सुधारें

अच्छा काम जो सभी उपयोग के मामलों से संबंधित है। कमरे के एक बिट refactoring के लिए शायद लेकिन अभी भी upvote !!
जीन रेमंड डेहर

12

स्विफ्ट 4

var isModal: Bool {
    return presentingViewController != nil ||
           navigationController?.presentingViewController?.presentedViewController === navigationController ||
           tabBarController?.presentingViewController is UITabBarController
}

Swift 4.2 / iOS 12. अभी भी अच्छी तरह से काम करता है, लेकिन इस बात से अवगत रहें कि नेवीगेशनकंट्रोलर। प्रस्तुत किया)।
एली बर्क

7

स्विफ्ट 5. स्वच्छ और सरल।

if navigationController.presentingViewController != nil {
    // Navigation controller is being presented modally
}

1
इसने मेरे लिए चाल
चली

3

जैसा कि यहां कई लोग सुझाव देते हैं, कि "जाँच" विधियाँ सभी मामलों के लिए अच्छी तरह से काम नहीं करती हैं, मेरी परियोजना में मैं स्वयं उस प्रबंधन के समाधान के साथ आया हूं। मुद्दा यह है, हम आमतौर पर अपने दम पर प्रस्तुति का प्रबंधन करते हैं - यह वह नहीं है जो दृश्य के पीछे होता है और हमें आत्मनिरीक्षण करना होगा।

DEViewController.h फ़ाइल:

#import <UIKit/UIKit.h>

// it is a base class for all view controllers within a project
@interface DEViewController : UIViewController 

// specify a way viewcontroller, is presented  by another viewcontroller
// the presented view controller should manually assign the value to it
typedef NS_ENUM(NSUInteger, SSViewControllerPresentationMethod) {
    SSViewControllerPresentationMethodUnspecified = 0,
    SSViewControllerPresentationMethodPush,
    SSViewControllerPresentationMethodModal,
};
@property (nonatomic) SSViewControllerPresentationMethod viewControllerPresentationMethod;

// other properties/methods...
@end

प्रस्तुतियाँ अब इस तरह से प्रबंधित की जा सकती हैं:

नेविगेशन स्टैक पर धकेल दिया गया:

// DETestViewController inherits from DEViewController
DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodPush;
[self.navigationController pushViewController:vc animated:YES];

नेविगेशन के साथ औपचारिक रूप से प्रस्तुत:

DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodModal;
UINavigationController *nav = [[UINavigationController alloc]
                               initWithRootViewController:vc];
[self presentViewController:nav animated:YES completion:nil];

सामान्य रूप से प्रस्तुत:

DETestViewController *vc = [DETestViewController new];
vc.viewControllerPresentationMethod = SSViewControllerPresentationMethodModal;
[self presentViewController:vc animated:YES completion:nil];

इसके अलावा, DEViewControllerयदि उपरोक्त संपत्ति के बराबर है तो हम "चेकिंग" में एक वापसी जोड़ सकते हैं SSViewControllerPresentationMethodUnspecified:

- (BOOL)isViewControllerPushed
{
    if (self.viewControllerPresentationMethod != SSViewControllerPresentationMethodUnspecified) {
        return (BOOL)(self.viewControllerPresentationMethod == SSViewControllerPresentationMethodPush);
    }

    else {
        // fallback to default determination method
        return (BOOL)self.navigationController.viewControllers.count > 1;
    }
}

3

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

private var wasPushed: Bool {
    guard let vc = navigationController?.viewControllers.first where vc == self else {
        return true
    }

    return false
}

1
जो आपको हमेशा करना चाहिए - कृपया समझाएं कि क्यों?
अलेक्जेंडर अबाकुमोव

अलेक्जेंडर, तुम सच में नहीं होना चाहिए।
निकार्डन

2

अपने नियंत्रक को पता लगाने के लिए कि आप चाहते हैं कि कहीं भी नीचे दिए गए कोड का उपयोग न करें

if ([[[self.parentViewController childViewControllers] firstObject] isKindOfClass:[self class]]) {

    // Not pushed
}
else {

    // Pushed
}

मुझे उम्मीद है कि यह कोड किसी की भी मदद कर सकता है ...


1
जब आप एक ही व्यू कंट्रोलर क्लास का उपयोग कई स्थानों पर करते हैं तो यह विधि काम नहीं करती है, क्योंकि यह केवल उसी वर्ग की जांच करता है। आप स्पष्ट रूप से इसके बजाय समानता की जांच कर सकते हैं।
गक्कल

1

self.navigationController != nil इसका मतलब यह होगा कि यह एक नेविगेशन स्टैक में है।


25
अभी भी एक मोडल नेविगेशन कंट्रोलर में हो सकता है
कोल्डलॉजिक

इसलिए 'मोडल' और 'नेविगेशन स्टैक पर धकेल दिया' परस्पर अनन्य नहीं हैं। यह सोचना संदर्भ पर निर्भर करता है, लेकिन अगर self.navigationController नहीं है तो यह जांचना कि यह नेविगेशन नियंत्रक का एक दृश्य नियंत्रक है या नहीं इसका जवाब नहीं है।
डैनियल

@ डैनियल अंतर "धक्का दिया" और "प्रस्तुत" के बीच है। "मोडल 'का इससे कोई लेना-देना नहीं है। मेरा मानना ​​है कि" कोल्डलॉजिक "का मतलब" प्रस्तुत "होता है जब उन्होंने" मोडल "कहा।
rammdy

1
if let navigationController = self.navigationController, navigationController.isBeingPresented {
    // being presented
}else{
    // being pushed
}

0

यदि आप ios 5.0 का उपयोग कर रहे हैं या बाद में कृपया इस कोड का उपयोग करें

-(BOOL)isPresented
{
    if ([self isBeingPresented]) {
        // being presented
         return YES;
    } else if ([self isMovingToParentViewController]) {
        // being pushed
         return NO;
    } else {
        // simply showing again because another VC was dismissed
         return NO;
    }
}

0

स्विफ्ट 5
यह आसान एक्सटेंशन पिछले उत्तरों की तुलना में कुछ अधिक मामलों को संभालता है। ये मामले कुलपति हैं (देखें नियंत्रक) ऐप विंडो का रूट वीसी है, कुलपति को बच्चे के रूप में माता-पिता के वीसी में जोड़ा जाता है। यह केवल तभी वापस लौटने की कोशिश करता है जब व्यूकंट्रोलर को मामूली रूप से प्रस्तुत किया जाता है।

extension UIViewController {
    /**
      returns true only if the viewcontroller is presented.
    */
    var isModal: Bool {
        if let index = navigationController?.viewControllers.firstIndex(of: self), index > 0 {
            return false
        } else if presentingViewController != nil {
            if let parent = parent, !(parent is UINavigationController || parent is UITabBarController) {
                return false
            }
            return true
        } else if let navController = navigationController, navController.presentingViewController?.presentedViewController == navController {
            return true
        } else if tabBarController?.presentingViewController is UITabBarController {
            return true
        }
        return false
    }
}

Jonauz के जवाब के लिए धन्यवाद । फिर से अधिक अनुकूलन के लिए जगह है। कृपया उस मामले के बारे में चर्चा करें जिसे टिप्पणी अनुभाग में नियंत्रित करने की आवश्यकता है।


-1

जो कुछ सोच रहा है, उसके लिए ViewController को कैसे बताएं कि यह प्रस्तुत किया जा रहा है

अगर Aपेश / धक्का दे रहा हैB

  1. एक enumऔर propertyमें परिभाषित करेंB

    enum ViewPresentationStyle {
        case Push
        case Present
    }
    
    //and write property 
    
    var vcPresentationStyle : ViewPresentationStyle = .Push //default value, considering that B is pushed 
  2. अब Aव्यू कंट्रोलर में बताएं कि Bक्या इसे असाइन करके प्रस्तुत किया जा रहा हैpresentationStyle

    func presentBViewController() {
        let bViewController = B()
        bViewController.vcPresentationStyle = .Present //telling B that it is being presented
        self.presentViewController(bViewController, animated: true, completion: nil)
    }
  3. Bदृश्य नियंत्रक में उपयोग

    override func viewDidLoad() {
        super.viewDidLoad()
    
        if self.vcPresentationStyle == .Present {
            //is being presented 
        }
        else {
            //is being pushed
        }
    
    }

-2
id presentedController = self.navigationController.modalViewController;
if (presentedController) {
     // Some view is Presented
} else {
     // Some view is Pushed
}

यह आपको बताएगा कि व्यूकंट्रोलर प्रस्तुत किया गया है या धकेल दिया गया है


4
यह संपत्ति वंचित है।
मॉर्कॉम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.