Mam aplikację paska kart z wieloma widokami. Czy istnieje sposób, aby dowiedzieć się, czy konkretny UIViewController
jest obecnie widoczny z wnętrza UIViewController
? (szuka nieruchomości)
Mam aplikację paska kart z wieloma widokami. Czy istnieje sposób, aby dowiedzieć się, czy konkretny UIViewController
jest obecnie widoczny z wnętrza UIViewController
? (szuka nieruchomości)
Odpowiedzi:
Właściwość okna widoku jest różna od zera, jeśli widok jest obecnie widoczny, więc sprawdź widok główny w kontrolerze widoku:
Wywołanie metody widoku powoduje załadowanie widoku (jeśli nie jest załadowany), co jest niepotrzebne i może być niepożądane. Lepiej najpierw sprawdzić, czy jest już załadowany. Dodałem wywołanie do isViewLoaded, aby uniknąć tego problemu.
if (viewController.isViewLoaded && viewController.view.window) {
// viewController is visible
}
Od iOS9 stało się łatwiejsze:
if viewController.viewIfLoaded?.window != nil {
// viewController is visible
}
Lub jeśli masz UINavigationController zarządzający kontrolerami widoku, możesz zamiast tego sprawdzić jego właściwość visibleViewController .
topViewController
.
Oto rozwiązanie @ progrmr jako UIViewController
kategorię:
// 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
Istnieje kilka problemów z powyższymi rozwiązaniami. Jeśli używasz na przykład a UISplitViewController
, widok główny zawsze zwróci wartość true dla
if(viewController.isViewLoaded && viewController.view.window) {
//Always true for master view in split view controller
}
Zamiast tego zastosuj to proste podejście, które wydaje się działać dobrze w większości, jeśli nie we wszystkich przypadkach:
- (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;
}
Dla tych z Was, którzy szukają odpowiedzi Swift 2.2 :
if self.isViewLoaded() && (self.view.window != nil) {
// viewController is visible
}
i Swift 3 :
if self.isViewLoaded && (self.view.window != nil) {
// viewController is visible
}
W przypadku prezentacji modalnej na pełnym ekranie lub w kontekście, „widoczny” może oznaczać, że znajduje się na wierzchu stosu kontrolera widoku lub jest po prostu widoczny, ale zakryty przez inny kontroler widoku.
Aby sprawdzić, czy kontroler widoku „jest kontrolerem widoku z góry” różni się znacznie od „jest widoczny”, należy sprawdzić stos kontrolera widoku kontrolera nawigacji kontrolera widoku.
Napisałem kawałek kodu, aby rozwiązać ten problem:
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
jest własnością od Swift 3.0.
Chcesz korzystać z UITabBarController
„s selectedViewController
nieruchomości. Wszystkie kontrolery widoku podłączone do kontrolera paska kart mają tabBarController
zestaw właściwości, dzięki czemu możesz w dowolnym kodzie kontrolerów widoku:
if([[[self tabBarController] selectedViewController] isEqual:self]){
//we're in the active controller
}else{
//we are not
}
((UINavigationController *)self.tabBarController.selectedViewController).visibleViewController
Zrobiłem szybkie rozszerzenie w oparciu o odpowiedź @ progrmr.
Pozwala łatwo sprawdzić, czy UIViewController
na ekranie jest taki:
if someViewController.isOnScreen {
// Do stuff here
}
Rozszerzenie:
//
// UIViewControllerExtension.swift
//
import UIKit
extension UIViewController{
var isOnScreen: Bool{
return self.isViewLoaded() && view.window != nil
}
}
Dla moich celów, w kontekście kontrolera widoku kontenera, znalazłem to
- (BOOL)isVisible {
return (self.isViewLoaded && self.view.window && self.parentViewController != nil);
}
działa dobrze.
jeśli korzystasz z UINavigationController, a także chcesz obsługiwać widoki modalne, używam następujących opcji:
#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
}
Podejście, które zastosowałem dla modalnego kontrolera widoku, polegało na sprawdzeniu klasy prezentowanego kontrolera. Gdyby prezentowany kontroler widoku był ViewController2
, to wykonałbym trochę kodu.
UIViewController *vc = [self presentedViewController];
if ([vc isKindOfClass:[ViewController2 class]]) {
NSLog(@"this is VC2");
}
Znalazłem te funkcje w 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);
Być może powyższe funkcje mogą wykryć ViewController
pojawienie się lub nie.
XCode 6.4, dla iOS 8.4, włączony ARC
Oczywiście na wiele sposobów. Ten, który pracował dla mnie, jest następujący ...
@property(nonatomic, readonly, getter=isKeyWindow) BOOL keyWindow
Można tego użyć w dowolnym kontrolerze widoku w następujący sposób,
[self.view.window isKeyWindow]
Jeśli wywołasz tę właściwość -(void)viewDidLoad
, otrzymasz 0, a następnie, jeśli wywołasz ją po -(void)viewDidAppear:(BOOL)animated
otrzymaniu 1.
Mam nadzieję, że to komuś pomoże. Dzięki! Twoje zdrowie.
Jeśli korzystasz z kontrolera nawigacyjnego i chcesz tylko wiedzieć, czy korzystasz z aktywnego i najwyższego kontrolera, użyj:
if navigationController?.topViewController == self {
// Do something
}
Ta odpowiedź oparta jest na @mattdipasquale komentarzu .
Jeśli masz bardziej skomplikowany scenariusz, zobacz inne odpowiedzi powyżej.
możesz to sprawdzić według window
właściwości
if(viewController.view.window){
// view visible
}else{
// no visible
}
Potrzebowałem tego, aby sprawdzić, czy kontroler widoku jest aktualnie oglądanym kontrolerem, zrobiłem to, sprawdzając, czy jest jakiś przedstawiony kontroler widoku lub przepchnąłem nawigatora, publikuję go na wypadek, gdyby ktoś potrzebował takiego rozwiązania:
if presentedViewController != nil || navigationController?.topViewController != self {
//Viewcontroller isn't viewed
}else{
// Now your viewcontroller is being viewed
}
Korzystam z tego małego rozszerzenia w Swift 5 , dzięki czemu można łatwo i łatwo sprawdzić dowolny obiekt będący członkiem UIView .
extension UIView {
var isVisible: Bool {
guard let _ = self.window else {
return false
}
return true
}
}
Następnie używam go jako prostego sprawdzania instrukcji if ...
if myView.isVisible {
// do something
}
Mam nadzieję, że to pomoże! :)