Làm cách nào để biết chế độ xem của UIViewContoder có hiển thị không


Câu trả lời:


1098

Thuộc tính cửa sổ của khung nhìn không phải là không nếu chế độ xem hiện đang hiển thị, vì vậy hãy kiểm tra chế độ xem chính trong trình điều khiển chế độ xem:

Gọi phương thức xem làm cho chế độ xem tải (nếu nó không được tải) không cần thiết và có thể không mong muốn. Nó sẽ tốt hơn để kiểm tra đầu tiên để xem nếu nó đã được tải. Tôi đã thêm cuộc gọi vào isViewLoaded để tránh sự cố này.

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

Kể từ iOS9, nó đã trở nên dễ dàng hơn:

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

Hoặc nếu bạn có một UINavestionContaptor quản lý các bộ điều khiển xem, thay vào đó bạn có thể kiểm tra thuộc tính nhìn thấy của nó .


11
Một vấn đề với thuộc tính viewerViewControllee của UINavestionControll là trường hợp trong đóViewViewContaptor của bạn trình bày một bộ điều khiển xem chế độ. Trong trường hợp đó, chế độ xem phương thức trở thành hiển thịViewView, điều này có thể không mong muốn. Làm thế nào bạn sẽ xử lý đó?
Moshe

12
Điều này có lẽ là hiển nhiên đối với mọi người, nhưng đối với tôi, mã phải là self.isViewLoaded && self.view.window
JeffB6688

85
Hãy cẩn thận trong việc khái quát giải pháp này cho các tình huống khác. Ví dụ: nếu bạn đang sử dụng UIPageViewControll, các chế độ xem cho UIViewControllers không phải là trang hiện tại vẫn có thể có thuộc tính cửa sổ không phải vì chúng được hiển thị ngoài màn hình. Trong trường hợp này, tôi đã thành công khi tạo thuộc tính 'isC hiệnlyVisible' của riêng mình, được đặt trong viewDidAppear và viewDidDisappear.
evanflash

4
@Moshe trong trường hợp đó, sử dụng topViewController.
ma11hew28

3
Xin lưu ý rằng câu trả lời này không nói gì về khả năng hiển thị thực sự. Ví dụ: nếu ứng dụng ở chế độ nền phía trên câu lệnh IF sẽ nói CÓ trong khi chế độ xem không thực sự hiển thị.
Marek J.

89

Đây là giải pháp của @ progrmr như là một UIViewControllerdanh mục:

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

Có một vài vấn đề với các giải pháp trên. Nếu bạn đang sử dụng, ví dụ: a UISplitViewController, chế độ xem chính sẽ luôn trả về đúng cho

if(viewController.isViewLoaded && viewController.view.window) {
    //Always true for master view in split view controller
}

Thay vào đó, hãy thực hiện phương pháp đơn giản này có vẻ hoạt động tốt trong hầu hết các trường hợp, nếu không phải tất cả các trường hợp:

- (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
Điều này có còn đúng trong xCode 7.1.1 không? Bậc thầy trong UISplitViewControll của tôi đang trả về NO cho viewControll.view.window. Tôi có thể đang làm gì đó sai, nhưng tôi khá chắc chắn đây là trường hợp.
SAH

44

Đối với những bạn đang tìm kiếm một phiên bản Swift 2.2 của câu trả lời:

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

Swift 3 :

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

Không chắc chắn tại sao nhưng tôi thấy rằng làm self.view.window! = Nil khiến nó không bao giờ hoạt động ngay cả khi self.isViewLoaded là đúng. Sau khi loại bỏ, nó hoạt động tốt.
Micah Montoya

Điều này chỉ làm việc cho tôi trong viewDidAppear. Khi tôi thêm cái này vào viewWillAppear self.view.window! = Nil luôn xuất hiện nil
Lance Samaria

29

Đối với bản trình bày phương thức toàn màn hình hoặc trên toàn ngữ cảnh, "hiển thị" có thể có nghĩa là nó nằm trên đỉnh của trình điều khiển chế độ xem hoặc chỉ hiển thị nhưng được bao phủ bởi trình điều khiển chế độ xem khác.

Để kiểm tra xem bộ điều khiển xem "là bộ điều khiển chế độ xem trên cùng" khác với "hiển thị", bạn nên kiểm tra ngăn xếp bộ điều khiển xem của bộ điều khiển xem.

Tôi đã viết một đoạn mã để giải quyết vấn đề này:

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

Bài đăng hay! FYI isViewLoadedlà một tài sản kể từ Swift 3.0.
Yuchen Zhong

28

Bạn muốn sử dụng UITabBarController's selectedViewControllertài sản. Tất cả các bộ điều khiển xem được gắn vào bộ điều khiển thanh tab đều có một tabBarControllerbộ thuộc tính, do đó, bạn có thể, từ bất kỳ mã nào của bộ điều khiển xem:

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

2
Điều này không hoạt động nếu bộ điều khiển xem được chứa bên trong bộ điều khiển điều hướng và bộ điều khiển đó được thêm vào bộ điều khiển thanh tab. Cuộc gọi đến selectViewCont Bộ điều khiển sẽ trả về bộ điều khiển điều hướng chứ không phải bộ điều khiển xem hiện tại.
Anton Holmberg

2
@AntonHolmberg trong trường hợp đó, hãy lấy bộ điều khiển xem hiển thị như thế này:((UINavigationController *)self.tabBarController.selectedViewController).visibleViewController
ma11hew28

Hoặc thậm chí sử dụng thuộc tính 'self.tabBarControll.selectedIndex' nếu chúng ta đã đi xa đến mức này.
Vladimir Shutyuk

12

Tôi đã thực hiện một phần mở rộng nhanh chóng dựa trên câu trả lời của @ progrmr.

Nó cho phép bạn dễ dàng kiểm tra nếu một UIViewControllertrên màn hình như vậy:

if someViewController.isOnScreen {
    // Do stuff here
}

Phần mở rộng:

//
//  UIViewControllerExtension.swift
//

import UIKit

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

7

Đối với mục đích của tôi, trong ngữ cảnh của trình điều khiển xem container, tôi đã thấy rằng

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

hoạt động tốt


3

nếu bạn đang sử dụng một UINavestionControll và cũng muốn xử lý các chế độ xem theo chế độ, thì đây là những gì tôi sử dụng:

#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
Tôi đã tìm thấy cách này đáng tin cậy hơn câu trả lời được chấp nhận, khi có bộ điều khiển điều hướng. Điều này có thể được rút ngắn thành: if ([self.navlationControll.visibleViewControll isKindOfClass: [self class]]) {
Darren

3

Cách tiếp cận mà tôi đã sử dụng cho một trình điều khiển xem trình bày phương thức là kiểm tra lớp của trình điều khiển được trình bày. Nếu trình điều khiển khung nhìn được trình bày ViewController2thì tôi sẽ thực thi một số mã.

UIViewController *vc = [self presentedViewController];

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

3

Tôi tìm thấy các chức năng trong 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);

Có thể các chức năng trên có thể phát hiện ViewControllerđược xuất hiện hay không.


3

XCode 6.4, cho iOS 8.4, bật ARC

Rõ ràng rất nhiều cách để làm điều đó. Người đã làm việc cho tôi là ...

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

Điều này có thể được sử dụng trong bất kỳ trình điều khiển xem theo cách sau,

[self.view.window isKeyWindow]

Nếu bạn gọi thuộc tính này trong -(void)viewDidLoadbạn nhận được 0, thì nếu bạn gọi nó sau khi -(void)viewDidAppear:(BOOL)animatedbạn nhận được 1.

Hy vọng điều này sẽ giúp được ai đó. Cảm ơn! Chúc mừng.


3

Nếu bạn đang sử dụng bộ điều khiển điều hướng và chỉ muốn biết nếu bạn đang ở trong bộ điều khiển hoạt độngtrên cùng , thì hãy sử dụng:

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

Câu trả lời này dựa trên nhận xét của @mattdipasquale .

Nếu bạn có một kịch bản phức tạp hơn, hãy xem các câu trả lời khác ở trên.


điều này sẽ không bao giờ được gọi nếu ứng dụng chạy trong nền và sau đó ở phía trước. Tôi đang tìm kiếm một giải pháp trong đó tôi có thể kiểm tra xem trình điều khiển xem có hiển thị cho người dùng hay không. Người dùng có thể chạy nền ứng dụng trong vài ngày và khi nó trở lại nền trước, tôi muốn cập nhật giao diện người dùng. Làm ơn để tôi biết nếu bạn có thể giúp.
bibscy

2

bạn có thể kiểm tra nó bằng windowtài sản

if(viewController.view.window){

// view visible

}else{

// no visible

}

0

Tôi cần điều này để kiểm tra xem bộ điều khiển xem có phải là bộ điều khiển đã xem hiện tại không, tôi đã thực hiện nó thông qua kiểm tra xem có bộ điều khiển xem nào được trình bày hay được đẩy qua bộ điều hướng hay không, tôi sẽ đăng nó trong trường hợp có ai cần giải pháp như vậy:

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

0

Tôi sử dụng tiện ích mở rộng nhỏ này trong Swift 5 , giúp đơn giản và dễ dàng kiểm tra mọi đối tượng là thành viên của UIView .

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

Sau đó, tôi chỉ sử dụng nó như một câu lệnh if đơn giản ...

if myView.isVisible {
    // do something
}

Tôi hy vọng nó sẽ giúp! :)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.