У меня есть приложение панели вкладок, с множеством просмотров. Есть ли способ узнать, виден ли конкретный UIViewController
в настоящее время из UIViewController
? (ищет недвижимость)
Как узнать, видно ли представление UIViewController
Ответ 1
Свойство окна вида не равно nil, если вид в данный момент виден, поэтому проверьте основной вид в контроллере вида:
Вызов метода view приводит к загрузке представления (если оно не загружено), что является ненужным и может быть нежелательным. Лучше сначала проверить, загружен ли он. Я добавил вызов isViewLoaded, чтобы избежать этой проблемы.
if (viewController.isViewLoaded && viewController.view.window) {
// viewController is visible
}
С iOS9 стало проще:
if viewController.viewIfLoaded?.window != nil {
// viewController is visible
}
Или, если у вас есть UINavigationController, управляющий контроллерами представления, вы можете вместо этого проверить его свойство visibleViewController.
Ответ 2
Здесь решение @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
Ответ 3
Существует несколько проблем с вышеупомянутыми решениями. Если вы используете, например, 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;
}
Ответ 4
Для тех из вас, кто ищет версию ответа 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
}
Ответ 5
Вы хотите использовать свойство UITabBarController
selectedViewController
. Все контроллеры представлений, прикрепленные к контроллеру панели вкладок, имеют свойство tabBarController
, поэтому вы можете изнутри любого из кодов контроллеров представления:
if([[[self tabBarController] selectedViewController] isEqual:self]){
//we're in the active controller
}else{
//we are not
}
Ответ 6
Для модального представления в полноэкранном или контекстном режиме "видимый" может означать, что он находится над стеком контроллера представления или просто видим, но покрыт другим контроллером представления.
Чтобы проверить, отличается ли контроллер вида "контроллер вида сверху" от "видимого", необходимо проверить стек контроллера вида контроллера навигации.
Я написал кусок кода, чтобы решить эту проблему:
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
}
}
}
Ответ 7
Я сделал быстрое расширение, основанное на ответе @progrmr.
Это позволяет вам легко проверить, есть ли UIViewController
на экране:
if someViewController.isOnScreen {
// Do stuff here
}
Расширение:
//
// UIViewControllerExtension.swift
//
import UIKit
extension UIViewController{
var isOnScreen: Bool{
return self.isViewLoaded() && view.window != nil
}
}
Ответ 8
В моих целях, в контексте контроллера контейнера, я обнаружил, что
- (BOOL)isVisible {
return (self.isViewLoaded && self.view.window && self.parentViewController != nil);
}
работает хорошо.
Ответ 9
если вы используете 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
}
Ответ 10
Подход, который я использовал для модального представленного контроллера представлений, заключался в проверке класса представленного контроллера. Если представленный контроллер представления был ViewController2
, тогда я бы выполнил некоторый код.
UIViewController *vc = [self presentedViewController];
if ([vc isKindOfClass:[ViewController2 class]]) {
NSLog(@"this is VC2");
}
Ответ 11
Я нашел эти функции в UIViewController.h
.
/*
These four methods can be used in a view controller 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
появился или нет.
Ответ 12
XCode 6.4, для iOS 8.4, ARC включен
Очевидно, много способов сделать это. Тот, который работал у меня, следующий...
@property(nonatomic, readonly, getter=isKeyWindow) BOOL keyWindow
Это может использоваться в любом контроллере вида следующим образом:
[self.view.window isKeyWindow]
Если вы вызываете это свойство в -(void)viewDidLoad
, вы получаете 0, то, если вы вызываете это после -(void)viewDidAppear:(BOOL)animated
, вы получаете 1.
Надеюсь, это поможет кому-то. Благодарю! Приветствия.
Ответ 13
Если вы используете контроллер навигации и хотите знать, находитесь ли вы в активном и самом верхнем контроллере, используйте:
if navigationController?.topViewController == self {
// Do something
}
Этот ответ основан на комментарии @mattdipasquale.
Если у вас более сложный сценарий, см. другие ответы выше.
Ответ 14
вы можете проверить его на window
property
if(viewController.view.window){
// view visible
}else{
// no visible
}
Ответ 15
Так как UIAlertController
получен из UIViewController
, вы можете просто использовать isBeingPresented
if (alertController.isBeingPresented) {
// alert is showing
}
Ответ 16
Мне нужно было это, чтобы проверить, является ли контроллер представления текущим просмотренным контроллером, я сделал это путем проверки, есть ли какой-либо представленный контроллер представления или протолкнул через навигатор, я отправляю это в случае, если кому-то нужно такое решение:
if presentedViewController != nil || navigationController?.topViewController != self {
//Viewcontroller isn't viewed
}else{
// Now your viewcontroller is being viewed
}
Ответ 17
Я использую это небольшое расширение в Swift 5, что позволяет легко и просто проверять наличие любого объекта, который является членом UIView.
extension UIView {
var isVisible: Bool {
guard let _ = self.window else {
return false
}
return true
}
}
Затем я просто использую его как простую проверку операторов if...
if myView.isVisible {
// do something
}
Надеюсь, это поможет! :)