我有一个带有多个视图的选项卡应用程序。有没有一种方法可以从UIViewController
中知道当前是否可见特定的UIViewController
?(寻找属性)
我有一个带有多个视图的选项卡应用程序。有没有一种方法可以从UIViewController
中知道当前是否可见特定的UIViewController
?(寻找属性)
如果视图当前可见,则视图的window property为非nil,因此请检查视图控制器中的主视图:
调用view方法会导致视图加载(如果尚未加载),这是不必要且可能不希望发生的。最好先检查是否已加载。我已添加了对isViewLoaded的调用以避免此问题。
if (viewController.isViewLoaded && viewController.view.window) {
// viewController is visible
}
iOS9之后,它变得更加容易了:
if viewController.viewIfLoaded?.window != nil {
// viewController is visible
}
或者,如果您有一个管理视图控制器的UINavigationController,您可以检查其visibleViewController属性。
topViewController
。 - ma11hew28这是@progrmr的解决方案,作为UIViewController
类别:
// 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
上述解决方案存在几个问题。例如,如果您正在使用 UISplitViewController
,则主视图将始终返回 true。
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;
}
如果您正在寻找关于Swift 2.2的答案:
if self.isViewLoaded() && (self.view.window != nil) {
// viewController is visible
}
以及 Swift 3:
if self.isViewLoaded && (self.view.window != nil) {
// viewController is visible
}
对于超出全屏或上下文模态呈现,"可见"可能意味着它在视图控制器堆栈的顶部或仅可见但被另一个视图控制器覆盖。
检查视图控制器是否为"顶部视图控制器"与"可见"相差很大,您应该检查视图控制器的导航控制器的视图控制器堆栈。
我编写了一段代码来解决这个问题:
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
}
}
}
isViewLoaded
自 Swift 3.0 起已成为属性。 - Yuchen您要使用UITabBarController
的selectedViewController
属性。所有连接到选项卡栏控制器的视图控制器都有一个设置了tabBarController
属性,因此在任何视图控制器的代码中,您可以:
if([[[self tabBarController] selectedViewController] isEqual:self]){
//we're in the active controller
}else{
//we are not
}
((UINavigationController *)self.tabBarController.selectedViewController).visibleViewController
- ma11hew28我基于@progrmr的答案创建了一个Swift扩展。
它使你可以轻松地检查UIViewController
是否在屏幕上,如下所示:
if someViewController.isOnScreen {
// Do stuff here
}
扩展:
//
// UIViewControllerExtension.swift
//
import UIKit
extension UIViewController{
var isOnScreen: Bool{
return self.isViewLoaded() && view.window != nil
}
}
在容器视图控制器的情况下,根据我的需求,我发现
- (BOOL)isVisible {
return (self.isViewLoaded && self.view.window && self.parentViewController != nil);
}
运行良好。
我在 Swift 5 中使用了这个小扩展,它使得检查任何属于 UIView 的对象变得简单易懂。
extension UIView {
var isVisible: Bool {
guard let _ = self.window else {
return false
}
return true
}
}
if myView.isVisible {
// do something
}
如果显示视图已经存在于窗口层次结构栈中,则会出现良好的视图。因此我们可以扩展我们的类以实现此功能。
extension UIViewController {
var isViewAppeared: Bool { viewIfLoaded?.isAppeared == true }
}
extension UIView {
var isAppeared: Bool { window != nil }
}