UIViewController의보기가 보이는지 확인하는 방법


답변:


1097

뷰가 현재 표시되어있는 경우 뷰의 창 속성 은 0이 아닙니다. 뷰 컨트롤러에서 기본 뷰를 확인하십시오.

view 메소드를 호출하면 뷰가로드되고 (로드되지 않은 경우) 불필요 할 수 있습니다. 이미로드되어 있는지 먼저 확인하는 것이 좋습니다. 이 문제를 피하기 위해 isViewLoaded에 대한 호출을 추가했습니다.

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

iOS9부터는 더 쉬워졌습니다.

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

또는 뷰 컨트롤러를 관리하는 UINavigationController가있는 경우 visibleViewController 속성을 대신 확인할 수 있습니다 .


11
UINavigationController의 visibleViewControllee 속성과 관련된 한 가지 문제는 visibleViewController가 모달 뷰 컨트롤러를 제공하는 경우입니다. 이 경우 모달 뷰는 visibleViewController가되므로 바람직하지 않습니다. 어떻게 처리하겠습니까?
Moshe 2016 년

12
이것은 아마도 모든 사람에게 명백 할 것이지만, 나에게있어 코드는 self.isViewLoaded && self.view.window
여야했다

85
이 솔루션을 다른 상황에 일반화 할 때는주의하십시오. 예를 들어, UIPageViewController를 사용하는 경우 현재 페이지가 아닌 UIViewController에 대한보기는 화면 밖에서 렌더링되기 때문에 여전히 0이 아닌 창 속성을 가질 수 있습니다. 이 경우 viewDidAppear 및 viewDidDisappear에 설정된 자체 'isCurrentlyVisible'속성을 만드는 데 성공했습니다.
evanflash

4
이 경우 @Moshe를 사용하십시오 topViewController.
ma11hew28

3
이 답변은 실제 가시성에 대해 아무 것도 말하지 않습니다. 예를 들어 앱이 백그라운드에서 백그라운드에있는 경우보기가 실제로 보이지 않는 경우 IF 문은 YES로 표시됩니다.
Marek J.

89

UIViewController카테고리 로 @progrmr의 솔루션은 다음과 같습니다 .

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

47

위의 솔루션에는 몇 가지 문제가 있습니다. 예를 들어를 사용하는 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;
}

1
xCode 7.1.1에서도 이것이 사실입니까? 내 UISplitViewController의 마스터가 viewController.view.window에 대해 NO를 반환합니다. 내가 잘못하고있을 수도 있지만 이것이 사실이라고 확신합니다.
SAHM

44

Swift 2.2 버전의 답변 을 찾고있는 사람들을 위해 :

if self.isViewLoaded() && (self.view.window != nil) {
     // viewController is visible
}

스위프트 3 :

if self.isViewLoaded && (self.view.window != nil) {
         // viewController is visible
}

이유는 확실하지 않지만 self.view.window! = nil을 수행하면 self.isViewLoaded가 true 일 때도 작동하지 않습니다. 일단 제거되면 잘 작동합니다.
Micah Montoya

이것은 viewDidAppear에서만 나를 위해 일했습니다. 이것을 viewWillAppear에 추가했을 때 self.view.window! = nil은 항상 nil이되었습니다
Lance Samaria

29

전체 화면 또는 상황에 맞는 모달 프레젠테이션의 경우 "표시"는 뷰 컨트롤러 스택의 상단에 있거나 다른 뷰 컨트롤러에 의해 표시되는 것을 의미 할 수 있습니다.

뷰 컨트롤러 "상위 뷰 컨트롤러"가 "표시"와 다른지 확인하려면 뷰 컨트롤러의 내비게이션 컨트롤러의 뷰 컨트롤러 스택을 확인해야합니다.

이 문제를 해결하기 위해 코드를 작성했습니다.

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

좋은 포스트! FYI isViewLoaded는 Swift 3.0 이후 숙박 시설입니다.
Yuchen Zhong

28

UITabBarControllerselectedViewController속성 을 사용하려고 합니다. 탭 막대 컨트롤러에 연결된 모든 뷰 컨트롤러에는 tabBarController속성이 설정되어 있으므로 모든 뷰 컨트롤러 코드 내에서 할 수 있습니다.

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

2
뷰 컨트롤러가 탐색 컨트롤러에 포함되어 있고 해당 컨트롤러가 탭 막대 컨트롤러에 추가 된 경우에는 작동하지 않습니다. selectedViewController를 호출하면 현재보기 컨트롤러가 아닌 내비게이션 컨트롤러가 반환됩니다.
Anton Holmberg

2
이 경우 @AntonHolmberg는 다음과 같은 가시적 뷰 컨트롤러를 가져옵니다.((UINavigationController *)self.tabBarController.selectedViewController).visibleViewController
ma11hew28

또는 지금까지 갔다면 'self.tabBarController.selectedIndex'속성을 사용하십시오.
Vladimir Shutyuk

12

@progrmr의 답변을 기반으로 신속한 확장을했습니다.

다음 UIViewController과 같이 a 가 화면에 있는지 쉽게 확인할 수 있습니다 .

if someViewController.isOnScreen {
    // Do stuff here
}

확장 :

//
//  UIViewControllerExtension.swift
//

import UIKit

extension UIViewController{
    var isOnScreen: Bool{
        return self.isViewLoaded() && view.window != nil
    }
}

7

내 목적을 위해 컨테이너 뷰 컨트롤러와 관련하여

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

잘 작동합니다.


3

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
}

2
네비게이션 컨트롤러를 사용할 수있을 때이 방법이 허용되는 답변보다 더 신뢰할 수 있음을 발견했습니다. if ([self.navigationController.visibleViewController isKindOfClass : [self class]]) {
Darren

3

내가 모달 제시 뷰 컨트롤러에 사용한 접근법은 제시된 컨트롤러의 클래스를 확인하는 것이 었습니다. 제시된 뷰 컨트롤러 인 경우 ViewController2코드를 실행합니다.

UIViewController *vc = [self presentedViewController];

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

3

에서 해당 기능을 찾았습니다 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이 나타나는지 여부를 감지 할 수 있습니다 .


3

XCode 6.4, iOS 8.4, ARC 사용

분명히 많은 방법이 있습니다. 나를 위해 일한 것은 다음과 같습니다.

@property(nonatomic, readonly, getter=isKeyWindow) BOOL keyWindow

다음과 같은 방식으로 모든 뷰 컨트롤러에서 사용할 수 있습니다.

[self.view.window isKeyWindow]

이 속성을 호출 -(void)viewDidLoad하면 0이되고 -(void)viewDidAppear:(BOOL)animated1을 얻은 후에 호출하면

이것이 누군가를 돕기를 바랍니다. 감사! 건배.


3

내비게이션 컨트롤러 를 사용 중이고 활성 컨트롤러 와 최상위 컨트롤러 에 있는지 확인하려면 다음을 사용하십시오.

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

이 답변은 @mattdipasquale 의 댓글을 기반으로 합니다.

더 복잡한 시나리오가있는 경우 위의 다른 답변을 참조하십시오.


앱이 백그라운드에서 전경으로 이동하면 호출되지 않습니다. 뷰 컨트롤러가 사용자에게 표시되는지 여부를 확인할 수있는 솔루션을 찾고 있습니다. 사용자는 며칠 동안 앱을 백그라운드에서 배경으로 만들 수 있으며 다시 포 그라운드로 돌아 오면 UI를 업데이트하고 싶습니다. 도움이 필요하면 알려주십시오.
bibscy

2

당신은 window속성으로 확인할 수 있습니다

if(viewController.view.window){

// view visible

}else{

// no visible

}

0

뷰 컨트롤러가 현재 본 컨트롤러인지 확인하려면 이것이 필요했습니다.보기 컨트롤러가 있거나 탐색기를 통해 푸시되었는지 확인하여 확인했습니다. 누군가 그러한 솔루션이 필요한 경우 게시하고 있습니다.

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

0

이 작은 확장 기능을 Swift 5 에서 사용하면 UIView의 멤버 인 객체를 간단하고 쉽게 확인할 수 있습니다.

extension UIView {
    var isVisible: Bool {
        guard let _ = self.window else {
            return false
        }
        return true
    }
}

그런 다음 간단한 if 문 확인으로 사용합니다 ...

if myView.isVisible {
    // do something
}

도움이 되길 바랍니다! :)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.