Ho un'applicazione della barra delle schede, con molte visualizzazioni. C'è un modo per sapere se un particolare UIViewController
è attualmente visibile dall'interno UIViewController
? (alla ricerca di un immobile)
Ho un'applicazione della barra delle schede, con molte visualizzazioni. C'è un modo per sapere se un particolare UIViewController
è attualmente visibile dall'interno UIViewController
? (alla ricerca di un immobile)
Risposte:
La proprietà della finestra della vista è nulla se una vista è attualmente visibile, quindi controlla la vista principale nel controller della vista:
Il richiamo del metodo view provoca il caricamento della view (se non viene caricata) che non è necessario e potrebbe essere indesiderabile. Sarebbe meglio controllare prima di vedere se è già caricato. Ho aggiunto la chiamata a isViewLoaded per evitare questo problema.
if (viewController.isViewLoaded && viewController.view.window) {
// viewController is visible
}
Da iOS9 è diventato più facile:
if viewController.viewIfLoaded?.window != nil {
// viewController is visible
}
Oppure, se hai un UINavigationController che gestisce i controller di visualizzazione, puoi invece controllare la sua proprietà visibleViewController .
topViewController
.
Ecco la soluzione di @ progrmr come UIViewController
categoria:
// 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
Ci sono un paio di problemi con le soluzioni sopra. Se si utilizza, ad esempio, a UISplitViewController
, la vista principale tornerà sempre vera per
if(viewController.isViewLoaded && viewController.view.window) {
//Always true for master view in split view controller
}
Prendi invece questo semplice approccio che sembra funzionare bene nella maggior parte, se non in tutti i casi:
- (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;
}
Per quelli di voi che cercano una versione Swift 2.2 della risposta:
if self.isViewLoaded() && (self.view.window != nil) {
// viewController is visible
}
e Swift 3 :
if self.isViewLoaded && (self.view.window != nil) {
// viewController is visible
}
Per una presentazione modale a schermo intero o contestuale, "è visibile" potrebbe significare che si trova in cima allo stack del controller di visualizzazione o è appena visibile ma è coperto da un altro controller di visualizzazione.
Per verificare se il controller di visualizzazione "è il controller della vista dall'alto" è abbastanza diverso da "è visibile", è necessario controllare lo stack del controller di visualizzazione del controller di navigazione del controller di visualizzazione.
Ho scritto un pezzo di codice per risolvere questo problema:
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
è una proprietà dal Swift 3.0.
Si desidera utilizzare la UITabBarController
's selectedViewController
proprietà. Tutti i controller di visualizzazione collegati a un controller della barra delle schede hanno un tabBarController
set di proprietà, quindi è possibile, all'interno di qualsiasi codice del controller di visualizzazione:
if([[[self tabBarController] selectedViewController] isEqual:self]){
//we're in the active controller
}else{
//we are not
}
((UINavigationController *)self.tabBarController.selectedViewController).visibleViewController
Ho fatto una rapida estensione in base alla risposta di @ progrmr.
Ti permette di controllare facilmente se uno UIViewController
è sullo schermo in questo modo:
if someViewController.isOnScreen {
// Do stuff here
}
L'estensione:
//
// UIViewControllerExtension.swift
//
import UIKit
extension UIViewController{
var isOnScreen: Bool{
return self.isViewLoaded() && view.window != nil
}
}
Per i miei scopi, nel contesto di un controller di visualizzazione contenitore, l'ho trovato
- (BOOL)isVisible {
return (self.isViewLoaded && self.view.window && self.parentViewController != nil);
}
funziona bene.
se stai utilizzando un UINavigationController e vuoi anche gestire le viste modali, utilizzo ciò che segue:
#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
}
L'approccio che ho usato per un controller di visualizzazione presentato modale era di verificare la classe del controller presentato. Se il controller della vista presentato fosse ViewController2
allora eseguirò del codice.
UIViewController *vc = [self presentedViewController];
if ([vc isKindOfClass:[ViewController2 class]]) {
NSLog(@"this is VC2");
}
Ho trovato quelle funzioni in 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);
Forse le funzioni di cui sopra possono rilevare la ViewController
comparsa o meno.
XCode 6.4, per iOS 8.4, ARC abilitato
Ovviamente molti modi per farlo. Quello che ha funzionato per me è il seguente ...
@property(nonatomic, readonly, getter=isKeyWindow) BOOL keyWindow
Questo può essere utilizzato in qualsiasi controller di visualizzazione nel modo seguente,
[self.view.window isKeyWindow]
Se chiami questa proprietà in -(void)viewDidLoad
ottieni 0, allora se la chiami dopo -(void)viewDidAppear:(BOOL)animated
aver ottenuto 1.
Spero che questo aiuti qualcuno. Grazie! Saluti.
Se stai usando un controller di navigazione e vuoi solo sapere se sei nel controller attivo e più in alto , usa:
if navigationController?.topViewController == self {
// Do something
}
Questa risposta si basa sul commento di @mattdipasquale .
Se hai uno scenario più complicato, vedi le altre risposte sopra.
puoi verificarlo per window
proprietà
if(viewController.view.window){
// view visible
}else{
// no visible
}
Avevo bisogno di questo per verificare se il controller di visualizzazione è il controller visualizzato corrente, l'ho fatto controllando se c'è un controller di visualizzazione presentato o inviato tramite il navigatore, lo sto pubblicando nel caso in cui qualcuno avesse bisogno di una tale soluzione:
if presentedViewController != nil || navigationController?.topViewController != self {
//Viewcontroller isn't viewed
}else{
// Now your viewcontroller is being viewed
}
Uso questa piccola estensione in Swift 5 , che lo rende semplice e facile da controllare per qualsiasi oggetto membro di UIView .
extension UIView {
var isVisible: Bool {
guard let _ = self.window else {
return false
}
return true
}
}
Quindi, lo uso solo come un semplice controllo if statement ...
if myView.isVisible {
// do something
}
Spero possa essere d'aiuto! :)