Как узнать, виден ли вид UIViewController



У меня есть приложение tabbar, с большим количеством просмотров. Есть ли способ узнать, является ли конкретный UIViewController в настоящее время видимым из UIViewController? (ищу недвижимость)

696   15  

15 ответов:

вид окне Свойства не равно нулю, если вид в настоящее время виден, поэтому проверьте основной вид в контроллере вида:

[EDIT] вызов view метод вызывает загрузку представления (если оно не загружено), что является ненужным и может быть нежелательным. Было бы лучше сначала проверить, если он уже загружен. Я добавил вызов isViewLoaded, чтобы избежать этой проблемы.

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

или если вы у UINavigationController, управляющего контроллерами представления, вы можете проверить его visibleViewController свойство вместо этого.

кроме того, в Swift на iOS 9 (или более поздней версии):

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

вот решение @ 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
}

вы хотите использовать UITabBarController ' s selectedViewController собственность. Все контроллеры вида, подключенные к контроллеру панели вкладок, имеют tabBarController набор свойств, так что вы можете, из любого кода контроллера вида:

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

Для над-полноэкранного или над-контекстного модального представления "виден" может означать, что он находится поверх стека контроллера вида или просто виден, но покрыт другим контроллером вида.

чтобы проверить, что контроллер вида "является контроллером вида сверху" сильно отличается от "виден", вы должны проверить стек контроллера вида контроллера навигации контроллера вида.

Я написал кусок кода, чтобы решить эту проблему:

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
        }
    }
}

Я сделал быстрое расширение на основе ответа @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
}

Я нашел эти функции в 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.

надеюсь, это кому-то поможет. Спасибо! Овации.

вы можете проверить это с помощью window свойства

if(viewController.view.window){

// view visible

}else{

// no visible

}

подход, который я использовал для модального представленного контроллера вида, состоял в том, чтобы проверить класс представленного контроллера. Если представленный контроллер вида был ViewController2 тогда я бы выполнил некоторый код.

UIViewController *vc = [self presentedViewController];

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

Если вы используете навигационный контроллер и просто хотите знать, находитесь ли вы в активный и верхний контроллер, а затем использовать:

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

этот ответ основан на @mattdipasqualeкомментарий.

Если у вас есть более сложный сценарий, см. другие ответы выше.

Мне нужно было это, чтобы проверить, является ли контроллер вида текущим контроллером просмотра, я сделал это, проверив, есть ли какой-либо представленный контроллер вида или проталкивается через навигатор, я публикую его в случае, если кому-то нужно такое решение:

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

Comments

    Ничего не найдено.