Как определить, виден ли вид UIViewController - PullRequest
527 голосов
/ 06 мая 2010

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

Ответы [ 15 ]

1014 голосов
/ 06 мая 2010

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

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

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

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

Также в Swift на iOS 9 (или более поздней версии):

if viewController.viewIfLoaded?.window != nil {
    // viewController is visible
}
89 голосов
/ 30 июня 2011

Вот решение @ 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
45 голосов
/ 04 февраля 2014

Существует несколько проблем с вышеуказанными решениями. Если вы используете, например, 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;
}
42 голосов
/ 04 апреля 2016

Для тех, кто ищет вариант ответа 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
}
28 голосов
/ 06 мая 2010

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

if([[[self tabBarController] selectedViewController] isEqual:self]){
     //we're in the active controller
}else{
     //we are not
}
24 голосов
/ 11 декабря 2014

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

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

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

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
        }
    }
}
12 голосов
/ 20 мая 2015

Я сделал быстрое расширение на основе ответа @ progrmr.

Позволяет легко проверить, есть ли на экране UIViewController, например:

if someViewController.isOnScreen {
    // Do stuff here
}

Расширение:

//
//  UIViewControllerExtension.swift
//

import UIKit

extension UIViewController{
    var isOnScreen: Bool{
        return self.isViewLoaded() && view.window != nil
    }
}
7 голосов
/ 18 июня 2014

Для моих целей в контексте контроллера представления контейнера я обнаружил, что

- (BOOL)isVisible {
    return (self.isViewLoaded && self.view.window && self.parentViewController != nil);
}

хорошо работает.

3 голосов
/ 25 июля 2016

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

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

Этот ответ основан на комментарии @ mattdipasquale

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

3 голосов
/ 24 июля 2015

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.

Надеюсь, это кому-нибудь поможет. Спасибо! Приветствия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...