У меня есть приложение панели вкладок, с множеством просмотров. Есть ли способ узнать, UIViewController
видно ли конкретное в данный момент из UIViewController
? (ищет недвижимость)
У меня есть приложение панели вкладок, с множеством просмотров. Есть ли способ узнать, UIViewController
видно ли конкретное в данный момент из UIViewController
? (ищет недвижимость)
Ответы:
Свойство окна представления не равно nil, если представление в настоящее время видно, поэтому проверьте основной вид в контроллере представления:
Вызов метода view приводит к загрузке представления (если оно не загружено), что является ненужным и может быть нежелательным. Было бы лучше сначала проверить, загружен ли он. Я добавил вызов isViewLoaded, чтобы избежать этой проблемы.
if (viewController.isViewLoaded && viewController.view.window) {
// viewController is visible
}
С iOS9 стало проще:
if viewController.viewIfLoaded?.window != nil {
// viewController is visible
}
Или, если у вас есть UINavigationController, управляющий контроллерами представления, вы можете вместо этого проверить его свойство visibleViewController .
topViewController
.
Вот решение @ 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
Есть несколько проблем с вышеуказанными решениями. Если вы используете, например, a 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
}
и Свифт 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.
Вы хотите использовать UITabBarController
«S selectedViewController
собственности. Все контроллеры представления, подключенные к контроллеру панели вкладок, имеют tabBarController
набор свойств, так что вы можете сделать это из любого кода контроллера представления:
if([[[self tabBarController] selectedViewController] isEqual:self]){
//we're in the active controller
}else{
//we are not
}
((UINavigationController *)self.tabBarController.selectedViewController).visibleViewController
Я сделал быстрое расширение на основе ответа @ progrmr.
Это позволяет вам легко проверить, есть ли 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);
}
работает хорошо.
Если вы используете 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
}
Подход, который я использовал для модального представленного контроллера представления, состоял в том, чтобы проверить класс представленного контроллера. Если бы представленный контроллер представления был ViewController2
тогда, я выполнил бы некоторый код.
UIViewController *vc = [self presentedViewController];
if ([vc isKindOfClass:[ViewController2 class]]) {
NSLog(@"this is VC2");
}
Я нашел эти функции в 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
появившееся или нет.
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.
Надеюсь, это кому-нибудь поможет. Спасибо! Приветствия.
Если вы используете контроллер навигации и просто хотите узнать, используете ли вы активный и самый верхний контроллер, используйте:
if navigationController?.topViewController == self {
// Do something
}
Этот ответ основан на комментарии @mattdipasquale .
Если у вас более сложный сценарий, посмотрите другие ответы выше.
Вы можете проверить это по window
свойству
if(viewController.view.window){
// view visible
}else{
// no visible
}
Мне нужно было это, чтобы проверить, является ли контроллер представления текущим просмотренным контроллером, я сделал это, проверив, есть ли представленный контроллер представления или протолкнул через навигатор, я отправляю это в случае, если кому-то нужно такое решение:
if presentedViewController != nil || navigationController?.topViewController != self {
//Viewcontroller isn't viewed
}else{
// Now your viewcontroller is being viewed
}
Я использую это небольшое расширение в Swift 5 , что позволяет легко и просто проверять наличие любого объекта, который является членом UIView .
extension UIView {
var isVisible: Bool {
guard let _ = self.window else {
return false
}
return true
}
}
Тогда я просто использую его как простую проверку операторов ...
if myView.isVisible {
// do something
}
Я надеюсь, что это помогает! :)