कैसे बताएं कि UIViewController का दृश्य दिखाई देता है या नहीं


569

मेरे पास एक टैब बार एप्लिकेशन है, जिसमें कई दृश्य हैं। क्या यह जानने का कोई तरीका है कि क्या कोई विशेष UIViewControllerवर्तमान में दिखाई दे रहा है UIViewController? (संपत्ति की तलाश में)


जवाबों:


1097

यदि वर्तमान में दृश्य दिखाई दे रहा है, तो दृश्य की विंडो गुण गैर-शून्य है, इसलिए दृश्य नियंत्रक में मुख्य दृश्य देखें:

दृश्य विधि को शामिल करने से दृश्य लोड हो जाता है (यदि इसे लोड नहीं किया गया है) जो अनावश्यक है और अवांछनीय हो सकता है। पहले यह देखना बेहतर होगा कि क्या यह पहले से लोड है। मैंने इस समस्या से बचने के लिए isViewLoaded में कॉल जोड़ा है।

if (viewController.isViewLoaded && viewController.view.window) {
    // viewController is visible
}

IOS9 के बाद से यह आसान हो गया है:

if viewController.viewIfLoaded?.window != nil {
    // viewController is visible
}

या यदि आपके पास व्यू कंट्रोलर्स को प्रबंधित करने वाला एक UINavigationController है, तो आप इसके बजाय इसके दृश्यदृश्य नियंत्रक को देख सकते हैं।


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

12
यह शायद सभी के लिए स्पष्ट है, लेकिन मेरे लिए कोड self.isViewLoaded && self.view.window होना चाहिए था
JeffB6688

85
अन्य स्थितियों के लिए इस समाधान को सामान्य करने में सावधानी बरतें। उदाहरण के लिए, यदि आप एक UIPageViewController का उपयोग कर रहे हैं, तो UIViewControllers के लिए विचार जो वर्तमान पृष्ठ नहीं हैं, उनके पास अभी भी एक गैर-शून्य विंडो संपत्ति हो सकती है क्योंकि उन्हें ऑफ-स्क्रीन प्रदान किया जा रहा है। इस मामले में, मुझे सफलता मिली है कि मैं अपना खुद का 'समकालिक रूप से अदृश्य' संपत्ति बना सकता हूं जो दृश्यदर्शी और दृश्यदर्शी दृश्य में सेट हो जाता है।
इवानफ्लेश

4
@ उस मामले में, उपयोग करें topViewController
ma11hew28

3
कृपया ध्यान दें कि यह उत्तर वास्तविक दृश्यता के बारे में कुछ नहीं कहता है। उदाहरण के लिए, यदि एप्लिकेशन पृष्ठभूमि के ऊपर है, तो IF कथन हां कहेगा जबकि दृश्य वास्तव में दिखाई नहीं दे रहा है।
मारेक जे

89

यहाँ एक UIViewControllerश्रेणी के रूप में @ progrmr का समाधान है :

// UIViewController+Additions.h

@interface UIViewController (Additions)

- (BOOL)isVisible;

@end


// UIViewController+Additions.m

#import "UIViewController+Additions.h"

@implementation UIViewController (Additions)

- (BOOL)isVisible {
    return [self isViewLoaded] && self.view.window;
}

@end

47

उपरोक्त समाधानों के साथ कुछ मुद्दे हैं। यदि आप उपयोग कर रहे हैं, उदाहरण के लिए, ए UISplitViewController, मास्टर दृश्य हमेशा के लिए सच हो जाएगा

if(viewController.isViewLoaded && viewController.view.window) {
    //Always true for master view in split view controller
}

इसके बजाय, यह सरल तरीका अपनाएं जो कि सभी मामलों में सबसे अच्छा काम करता है:

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

    //We are now invisible
    self.visible = false;
}

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

    //We are now visible
    self.visible = true;
}

1
क्या यह अभी भी xCode 7.1.1 में सही है? मेरे UISplitViewController में मास्टर viewController.view.window के लिए NO लौट रहा है। मैं कुछ गलत कर रहा हूँ, लेकिन मुझे पूरा यकीन है कि यह मामला है।
SAHM

44

आप में से उन लोगों के लिए जो उत्तर की एक स्विफ्ट 2.2 संस्करण की तलाश कर रहे हैं :

if self.isViewLoaded() && (self.view.window != nil) {
     // viewController is visible
}

और स्विफ्ट 3 :

if self.isViewLoaded && (self.view.window != nil) {
         // viewController is visible
}

यकीन नहीं क्यों, लेकिन मैंने पाया कि self.view.window! = Nil करने से यह कभी भी काम नहीं करता है जब self.isViewLoaded सच है। एक बार हटाने के बाद, यह ठीक काम करता है।
मीका मोंटोया

यह केवल मेरे लिए viewDidAppear में काम करता है। जब मैंने इसे जोड़ा गया देखने के लिए देखेंस्वागत स्व.व्यू.विंडो! = नील हमेशा शून्य पर आता है
लांस सामरिया

29

ओवर-फुल-स्क्रीन या ओवर-संदर्भ मोडल प्रस्तुति के लिए, "दृश्यमान" हो सकता है इसका मतलब यह दृश्य नियंत्रक स्टैक के शीर्ष पर है या बस दृश्यमान है लेकिन किसी अन्य दृश्य नियंत्रक द्वारा कवर किया गया है।

यह देखने के लिए कि क्या दृश्य नियंत्रक "शीर्ष दृश्य नियंत्रक" "दृश्यमान" से काफी अलग है, आपको दृश्य नियंत्रक के नेविगेशन नियंत्रक के दृश्य नियंत्रक स्टैक की जांच करनी चाहिए।

मैंने इस समस्या को हल करने के लिए एक कोड ऑफ़ कोड लिखा:

extension UIViewController {
    public var isVisible: Bool {
        if isViewLoaded {
            return view.window != nil
        }
        return false
    }

    public var isTopViewController: Bool {
        if self.navigationController != nil {
            return self.navigationController?.visibleViewController === self
        } else if self.tabBarController != nil {
            return self.tabBarController?.selectedViewController == self && self.presentedViewController == nil
        } else {
            return self.presentedViewController == nil && self.isVisible
        }
    }
}

अच्छा लेख! FYI करें isViewLoaded3.0 के बाद से एक संपत्ति है।
युकेन झोंग

28

आप उपयोग करना चाहते हैं UITabBarControllerकी selectedViewControllerसंपत्ति। टैब बार कंट्रोलर से जुड़े सभी व्यू कंट्रोलर्स के पास एक tabBarControllerप्रॉपर्टी सेट होता है, जिससे आप किसी भी व्यू कंट्रोलर के कोड में से:

if([[[self tabBarController] selectedViewController] isEqual:self]){
     //we're in the active controller
}else{
     //we are not
}

2
यह काम नहीं करता है अगर दृश्य नियंत्रक एक नेविगेशन नियंत्रक के अंदर निहित है और उस नियंत्रक को टैब बार नियंत्रक में जोड़ा जाता है। चयनितViewController के लिए कॉल नेविगेशन नियंत्रक को लौटाएगा न कि वर्तमान दृश्य नियंत्रक को।
एंटन होलबर्ग

2
उस मामले में @AntonHolmberg, दृश्य दृश्य नियंत्रक इस तरह से प्राप्त करें:((UINavigationController *)self.tabBarController.selectedViewController).visibleViewController
ma11hew28

या यहां तक ​​कि अगर हम अभी तक चले गए हैं, तो 'self.tabBarController.selectedIndex' संपत्ति का उपयोग करें।
व्लादिमीर Shutyuk

12

मैंने @ progrmr के उत्तर के आधार पर एक तेजी से विस्तार किया।

यह आपको आसानी से जांचने की अनुमति देता UIViewControllerहै कि क्या स्क्रीन पर ऐसा है:

if someViewController.isOnScreen {
    // Do stuff here
}

विस्तार:

//
//  UIViewControllerExtension.swift
//

import UIKit

extension UIViewController{
    var isOnScreen: Bool{
        return self.isViewLoaded() && view.window != nil
    }
}

7

मेरे उद्देश्यों के लिए, एक कंटेनर दृश्य नियंत्रक के संदर्भ में, मैंने पाया है कि

- (BOOL)isVisible {
    return (self.isViewLoaded && self.view.window && self.parentViewController != nil);
}

अच्छा काम करता है।


3

यदि आप एक UINavigationController का उपयोग कर रहे हैं और यह भी मॉडल विचारों को संभालना चाहते हैं, तो निम्नलिखित है जो मैं उपयोग करता हूं:

#import <objc/runtime.h>

UIViewController* topMostController = self.navigationController.visibleViewController;
if([[NSString stringWithFormat:@"%s", class_getName([topMostController class])] isEqualToString:@"NAME_OF_CONTROLLER_YOURE_CHECKING_IN"]) {
    //is topmost visible view controller
}

2
मैंने इस तरीके को स्वीकृत उत्तर की तुलना में अधिक विश्वसनीय पाया है, जब एक नेविगेशन नियंत्रक उपलब्ध है। इसे छोटा किया जा सकता है: अगर ([self.navigationController.vanishViewController isKindOfClass: [सेल्फ क्लास]])
डैरेन

3

मैंने जो मोडल प्रस्तुत दृश्य नियंत्रक के लिए उपयोग किया था वह प्रस्तुत नियंत्रक के वर्ग की जांच करना था। यदि प्रस्तुत दृश्य नियंत्रक था ViewController2तो मैं कुछ कोड निष्पादित करूंगा।

UIViewController *vc = [self presentedViewController];

if ([vc isKindOfClass:[ViewController2 class]]) {
    NSLog(@"this is VC2");
}

3

मुझे वो फंक्शन मिला UIViewController.h

/*
  These four methods can be used in a view controller's appearance callbacks to determine if it is being
  presented, dismissed, or added or removed as a child view controller. For example, a view controller can
  check if it is disappearing because it was dismissed or popped by asking itself in its viewWillDisappear:
  method by checking the expression ([self isBeingDismissed] || [self isMovingFromParentViewController]).
*/

- (BOOL)isBeingPresented NS_AVAILABLE_IOS(5_0);
- (BOOL)isBeingDismissed NS_AVAILABLE_IOS(5_0);

- (BOOL)isMovingToParentViewController NS_AVAILABLE_IOS(5_0);
- (BOOL)isMovingFromParentViewController NS_AVAILABLE_IOS(5_0);

हो सकता है कि उपरोक्त कार्यों का पता लगाया जा सके ViewControllerया नहीं।


3

IOS 8.4 के लिए XCode 6.4, ARC सक्षम है

जाहिर है इसे करने के बहुत सारे तरीके। जो मेरे लिए काम किया है वह निम्नलिखित है ...

@property(nonatomic, readonly, getter=isKeyWindow) BOOL keyWindow

यह किसी भी दृश्य नियंत्रक में निम्नलिखित तरीके से उपयोग किया जा सकता है,

[self.view.window isKeyWindow]

यदि आप इस संपत्ति को कॉल करते हैं -(void)viewDidLoadतो आपको 0 मिलता है, यदि आप -(void)viewDidAppear:(BOOL)animated1 प्राप्त करने के बाद इसे कॉल करते हैं ।

आशा है कि यह किसी की मदद करता है। धन्यवाद! चीयर्स।


3

यदि आप एक नेविगेशन नियंत्रक का उपयोग कर रहे हैं और बस यह जानना चाहते हैं कि क्या आप सक्रिय और सर्वोच्च नियंत्रक में हैं, तो उपयोग करें:

if navigationController?.topViewController == self {
    // Do something
}

यह उत्तर @mattdipasquale पर आधारित है की टिप्पणी ।

यदि आपके पास अधिक जटिल परिदृश्य है, तो ऊपर दिए गए अन्य उत्तर देखें।


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


0

मुझे यह देखने के लिए यह देखने की ज़रूरत है कि क्या दृश्य नियंत्रक वर्तमान देखे गए नियंत्रक है, मैंने इसे जाँच के माध्यम से किया है यदि कोई प्रस्तुत दृश्य नियंत्रक है या नाविक के माध्यम से धकेल दिया गया है, मैं इसे किसी ऐसे समाधान की आवश्यकता होने पर पोस्ट कर रहा हूं:

if presentedViewController != nil || navigationController?.topViewController != self {
      //Viewcontroller isn't viewed
}else{
     // Now your viewcontroller is being viewed 
}

0

मैं स्विफ्ट 5 में इस छोटे से विस्तार का उपयोग करता हूं , जो किसी भी वस्तु के लिए जांचना आसान और आसान रखता है जो कि यूआईवीईवाई का सदस्य है

extension UIView {
    var isVisible: Bool {
        guard let _ = self.window else {
            return false
        }
        return true
    }
}

फिर, मैं इसे एक साधारण के रूप में उपयोग करता हूं यदि स्टेटमेंट चेक ...

if myView.isVisible {
    // do something
}

मुझे उम्मीद है यह मदद करेगा! :)

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