如何检查当前是否正在显示一个 UIViewController?

22

如何检查当前是否正在显示一个UIViewController

我的UIViewController正在监听NSNotifications,即使它们没有被显示(即不可见)。因此,我可以有10个在后台的UIViewControllerNSNotificationCenter中观察NSNotifications。当一个NSNotification被发布并被UIViewController接收时,我想知道它当前是否正在显示。如果没有,我将设置一个布尔值,以便在视图呈现时处理它。如果它正在显示,则会立即执行更多操作,例如更新表格等等...


你是如何呈现视图控制器的视图的? - Tomasz Dubik
@tdubik:传统的方式,比如使用pushViewController。我没有使用StoryBoard或segues。 - ikevin8me
在这种情况下,您可以从UINavigationController类中检查topViewController。或者,如果您想处理多个控制器,请枚举viewControllers数组。 - Tomasz Dubik
回答你的问题之外,为什么不放弃使用NSNotifications,创建一个名为isVisibleBOOL变量,并在调用viewDidAppearviewDidDisappear时设置其值呢?然后在你的viewWillAppear(或其他地方)中,你只需要检查你的BOOL变量,就可以减少很多复杂性了。 - DBD
8个回答

21

您需要检查您的视图控制器是否在导航控制器视图控制器数组的顶部。以下是示例代码:

if (self.navigationController.topViewController == self) {
    //the view is currently displayed
}
你可以在viewWillAppear方法中使用这个来检查当前视图是否可见。

2
@DBD的回答更通用,由于问题标题不是那么具体,对未来的读者更有帮助。 - Zedenem
页面控制器怎么样?"self.nav" 的等价物是什么?比如说... self.page..? - user5306470

12

检查它是否附加到窗口。如果不是 nil,则它在层次结构中附加到屏幕(当然它可能超出屏幕边界、被其他视图遮挡或者有隐藏标志设置)

if (myViewController.view.window) {
  // I'm attached to the window
} else {
  // not attached to the window
}

2
接近了,但在检查视图是否在窗口中之前,您应该先检查视图是否已加载:if (self.isViewLoaded && self.view.window != nil) ... - rob mayoff
@rob。是的,你说得对。如果视图控制器没有加载并且你访问view对象,你会导致懒加载,这可能意味着将一些你还没有准备好使用的东西加载到内存中。虽然它仍然会给出正确的答案,但性能不理想。我曾经假设通知只会在视图加载时添加,而不是初始化,因为未初始化的视图永远不会被附加。尽管如此,这可能是一个不恰当的假设,如果没有其他说明的话,应该明确声明。 - DBD
1
这应该是正确的答案,包括@robmayoff的更改。 - Bill
同意@Bill...这确实应该是被接受的答案! - S1LENT WARRIOR

3
您可以在viewWillAppearviewWillDisappear方法中使用标志来实现此功能。

1

为每个ViewController指定标题,然后使用下面给出的代码获取当前ViewController的标题。

NSString *currentController = self.navigationController.visibleViewController.title;

Then check it by your title like this

if([currentController isEqualToString:@"myViewControllerTitle"]){

    //write your code according to View controller. 

}

1
为什么不在viewWillDisappear中移除通知监听器,并在viewWillAppear中添加它呢?
编辑:我误读了他的问题,抱歉。
建议答案:在viewDidDisappear和viewDidAppear中设置自己的标志(BOOL)。

这样做不行,因为它在移除时会错过所有通知。 - ikevin8me
那么,在 viewWillDisappear 中设置一个标志(BOOL)来指示视图不再可见呢?当它接收到通知时,检查该标志以查看视图是否可见。 - yuf
如果收到通知,我需要重新加载表格。如果没有收到通知,则这样做太昂贵了。此外,由于数据相同且代价太高,当视图再次出现时无需重新加载表格。 - ikevin8me
你的意思是说当视图消失时我自己设置一个标志吗?这是一个奇怪的解决方案,因为我认为苹果的API已经考虑到了我可以检测它。怎么做呢? - ikevin8me
我明白你的意思;我在考虑如果你将一个视图作为模态VC推送,并且使用透明背景,那么你是否认为底部视图是可见的。我会设置自己的标志,因为这样可以让我更加控制。我不知道view.superview(另一个答案)是否有效,但它似乎是可行的。 - yuf

0

回答这个问题现在已经太晚了。

要检查一个 UIViewController 的实例是否正在屏幕的顶部或是否正在显示在屏幕上,您可以进行如下检查:

// Get the topmost view showing on the screen as below
    UIViewController * currentVC = ((UINavigationController*)app.window.rootViewController).visibleViewController;

// Now check whether the viewcontroller you want to show is the same as the currently showing view controller.
    if (currentVC.class == myVC.class) {  // Here myVC is any/new instance of the viewcontroller you would like to check or show (if not shown).
         // If both are same then it returns true and executes this block of code.
    }

0

我认为检查viewController.view.superview应该可以工作。


我真的不明白。你是怎么进行比较的? - ikevin8me
if(viewController.view.superview != nil ) - Tomasz Dubik
问题是,你的视图可能已附加到一个父视图上,但该父视图可能未附加到你的窗口上,因此存在潜在漏洞导致它无法工作。 - DBD
在视图控制器中,何时可能会出现这种循环漏洞? - Tomasz Dubik

0

另一个选择是基于检查 window 属性的方式。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接