web-gelistirme-sc.com

Geçerli görüntüleyen UIViewController'ı AppDelegate.m'deki ekranda alın.

Ekrandaki mevcut UIViewController, bazı rozet görünümleri ayarlayarak APN'lerden gelen Push bildirimlerine yanıt vermelidir. Ama UIViewController yöntemini application:didReceiveRemoteNotification: of of AppDelegate.m ile nasıl alabilirim?

Şu anki UIViewController gösterimini elde etmek için self.window.rootViewController işlevini kullanmaya çalıştım, bu bir UINavigationViewController veya başka bir tür denetleyici olabilir. Ve visibleViewController __ UINavigationViewController özelliğinin, UIViewController ekranını almak için kullanılabileceğini öğrendim. Fakat eğer UINavigationViewController değilse ne yapabilirim?

Herhangi bir yardım takdir! İlgili kod aşağıdaki gibidir.

AppDelegate.m

...
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

    //I would like to find out which view controller is on the screen here.

    UIViewController *vc = [(UINavigationViewController *)self.window.rootViewController visibleViewController];
    [vc performSelector:@selector(handleThePushNotification:) withObject:userInfo];
}
...

ViewControllerA.m

- (void)handleThePushNotification:(NSDictionary *)userInfo{

    //set some badge view here

}
112
lu yuan

rootViewController işlevini, denetleyiciniz UINavigationController olmadığında da kullanabilirsiniz:

UIViewController *vc = self.window.rootViewController;

Kök görünümü denetleyicisini öğrendikten sonra, kullanıcı arabiriminizi nasıl oluşturduğunuza bağlıdır, ancak denetleyiciler hiyerarşisinde gezinmenin bir yolunu bulmaya başlayabilirsiniz.

Uygulamanızı tanımlama şekliniz hakkında daha fazla ayrıntı verirseniz, daha fazla ipucu verebilirim.

DÜZENLE:

En üstteki görünüm (görüntü denetleyicisini değil) istiyorsanız, kontrol edebilirsiniz.

[[[[UIApplication sharedApplication] keyWindow] subviews] lastObject];

her ne kadar bu görüş görünmez olabilir veya alt görüşlerinin bazıları tarafından bile ele alınabilir ...

yine, kullanıcı arayüzünüze bağlı, ancak bu yardımcı olabilir ...

96
sergio

Cıvatalandıkları ve kolayca yeniden kullanılabilecekleri kategorileri içeren çözümleri her zaman seviyorum.

Böylece UIWindow'da bir kategori oluşturdum. Şimdi UIWindow'da visibleViewController'ı çağırabilirsiniz ve bu, denetleyici hiyerarşisini arayarak görünür görüntü denetleyicisini elde etmenizi sağlar. Bu, navigasyon ve/veya sekme çubuğu denetleyicisi kullanıyorsanız çalışır. Önerecek başka bir denetleyiciniz varsa, lütfen bana bildirin ve ekleyebilirim.

UIWindow + PazLabs.h (başlık dosyası)

#import <UIKit/UIKit.h>

@interface UIWindow (PazLabs)

- (UIViewController *) visibleViewController;

@end

UIWindow + PazLabs.m (uygulama dosyası)

#import "UIWindow+PazLabs.h"

@implementation UIWindow (PazLabs)

- (UIViewController *)visibleViewController {
    UIViewController *rootViewController = self.rootViewController;
    return [UIWindow getVisibleViewControllerFrom:rootViewController];
}

+ (UIViewController *) getVisibleViewControllerFrom:(UIViewController *) vc {
    if ([vc isKindOfClass:[UINavigationController class]]) {
        return [UIWindow getVisibleViewControllerFrom:[((UINavigationController *) vc) visibleViewController]];
    } else if ([vc isKindOfClass:[UITabBarController class]]) {
        return [UIWindow getVisibleViewControllerFrom:[((UITabBarController *) vc) selectedViewController]];
    } else {
        if (vc.presentedViewController) {
            return [UIWindow getVisibleViewControllerFrom:vc.presentedViewController];
        } else {
            return vc;
        }
    }
}

@end

Hızlı Sürüm

public extension UIWindow {
    public var visibleViewController: UIViewController? {
        return UIWindow.getVisibleViewControllerFrom(self.rootViewController)
    }

    public static func getVisibleViewControllerFrom(_ vc: UIViewController?) -> UIViewController? {
        if let nc = vc as? UINavigationController {
            return UIWindow.getVisibleViewControllerFrom(nc.visibleViewController)
        } else if let tc = vc as? UITabBarController {
            return UIWindow.getVisibleViewControllerFrom(tc.selectedViewController)
        } else {
            if let pvc = vc?.presentedViewController {
                return UIWindow.getVisibleViewControllerFrom(pvc)
            } else {
                return vc
            }
        }
    }
}
94
zirinisp

NSNotificationCenter aracılığıyla bir bildirim de gönderebilirsiniz. Bu, görünüm denetleyicisi hiyerarşisini hareket ettirmenin zor olabileceği bir takım durumlarla başa çıkmanızı sağlar - örneğin, modacılar sunulurken,.

Örneğin.,

// MyAppDelegate.h
NSString * const UIApplicationDidReceiveRemoteNotification;

// MyAppDelegate.m
NSString * const UIApplicationDidReceiveRemoteNotification = @"UIApplicationDidReceiveRemoteNotification";

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {

    [[NSNotificationCenter defaultCenter]
     postNotificationName:UIApplicationDidReceiveRemoteNotification
     object:self
     userInfo:userInfo];
}

Görünüm Denetleyicilerinizin her birinde:

-(void)viewDidLoad {
    [[NSNotificationCenter defaultCenter] 
      addObserver:self
      selector:@selector(didReceiveRemoteNotification:)                                                  
      name:UIApplicationDidReceiveRemoteNotification
      object:nil];
}

-(void)viewDidUnload {
    [[NSNotificationCenter defaultCenter] 
      removeObserver:self
      name:UIApplicationDidReceiveRemoteNotification
      object:nil];
}

-(void)didReceiveRemoteNotification:(NSDictionary *)userInfo {
    // see http://stackoverflow.com/a/2777460/305149
   if (self.isViewLoaded && self.view.window) {
      // handle the notification
   }
}

Bu yaklaşımı, bir bildirim alındığında ve çeşitli görünüm denetleyicileri tarafından kullanıldığında güncellenmesi gereken cihaz kontrollerinde de kullanabilirsiniz. Bu durumda, ekle/kaldır gözlemci çağrılarını sırasıyla init ve dealloc yöntemlerinde kullanın. 

37

Swift'de UIApplication için basit uzantı (iPhone'da UITabBarController içindeki moreNavigationController ile bile ilgilenir):

extension UIApplication {
    class func topViewController(base: UIViewController? = UIApplication.sharedApplication().keyWindow?.rootViewController) -> UIViewController? {

        if let nav = base as? UINavigationController {
            return topViewController(base: nav.visibleViewController)
        }

        if let tab = base as? UITabBarController {
            let moreNavigationController = tab.moreNavigationController

            if let top = moreNavigationController.topViewController where top.view.window != nil {
                return topViewController(top)
            } else if let selected = tab.selectedViewController {
                return topViewController(selected)
            }
        }

        if let presented = base?.presentedViewController {
            return topViewController(base: presented)
        }

        return base
    }
}

Basit kullanım:

    if let rootViewController = UIApplication.topViewController() {
        //do sth with root view controller
    }

Mükemmel çalışıyor :-)

Temiz kod için GÜNCELLEME:

extension UIViewController {
    var top: UIViewController? {
        if let controller = self as? UINavigationController {
            return controller.topViewController?.top
        }
        if let controller = self as? UISplitViewController {
            return controller.viewControllers.last?.top
        }
        if let controller = self as? UITabBarController {
            return controller.selectedViewController?.top
        }
        if let controller = presentedViewController {
            return controller.top
        }
        return self
    }
}
37

Kod

İşte harika switch-case sözdizimi in Swift 3 kullanarak bir yaklaşım:

extension UIWindow {
    /// Returns the currently visible view controller if any reachable within the window.
    public var visibleViewController: UIViewController? {
        return UIWindow.visibleViewController(from: rootViewController)
    }

    /// Recursively follows navigation controllers, tab bar controllers and modal presented view controllers starting
    /// from the given view controller to find the currently visible view controller.
    ///
    /// - Parameters:
    ///   - viewController: The view controller to start the recursive search from.
    /// - Returns: The view controller that is most probably visible on screen right now.
    public static func visibleViewController(from viewController: UIViewController?) -> UIViewController? {
        switch viewController {
        case let navigationController as UINavigationController:
            return UIWindow.visibleViewController(from: navigationController.visibleViewController ?? navigationController.topViewController)

        case let tabBarController as UITabBarController:
            return UIWindow.visibleViewController(from: tabBarController.selectedViewController)

        case let presentingViewController where viewController?.presentedViewController != nil:
            return UIWindow.visibleViewController(from: presentingViewController?.presentedViewController)

        default:
            return viewController
        }
    }
}

Temel fikir, zirinisp'in cevabındakiyle aynıdır, sadece daha fazla Swift 3 benzeri bir sözdizimi kullanıyor.


Kullanım

Muhtemelen UIWindowExtension.Swift adında bir dosya oluşturmak istiyorsunuz. import UIKit deyimini içerdiğinden emin olun, şimdi yukarıdaki uzantı kodunu kopyalayın.

Çağrı tarafında, belirli bir görünüm denetleyicisi olmadan: kullanılabilir

if let visibleViewCtrl = UIApplication.shared.keyWindow?.visibleViewController {
    // do whatever you want with your `visibleViewCtrl`
}

Ya da görülebilir görünüm denetleyicinizin erişilebilir olduğunu biliyorsanız belirli bir görünüm denetleyicisinden:

if let visibleViewCtrl = UIWindow.visibleViewController(from: specificViewCtrl) {
    // do whatever you want with your `visibleViewCtrl`
}

Umut ediyorum bu yardım eder!

14
Dschee

İOS 8'in her şeyi mahvettiğini öğrendim. İOS 7'de, modal olarak sunulan bir UITransitionView varsa, görünüm hiyerarşisinde yeni bir UINavigationController vardır. Her neyse, işte bu benim kodumu en üstteki VC'yi alan kodum. getTopMostViewController işlevini çağırmak, presentViewController:animated:completion gibi bir ileti gönderebilmeniz için bir VC döndürmelidir. Amaç, modal bir VC sunmak için kullanabileceğiniz bir VC elde etmektir, bu yüzden büyük olasılıkla UINavigationController ve NOT'larda bulunan VC gibi konteyner sınıflarında duracak ve geri dönecektir. Bunu yapmak için de kodu uyarlamak zor olmamalı. Bu kodu iOS 6, 7 ve 8’de çeşitli durumlarda test ettim. Hata bulursanız lütfen bana bildirin.

+ (UIViewController*) getTopMostViewController
{
    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    if (window.windowLevel != UIWindowLevelNormal) {
        NSArray *windows = [[UIApplication sharedApplication] windows];
        for(window in windows) {
            if (window.windowLevel == UIWindowLevelNormal) {
                break;
            }
        }
    }

    for (UIView *subView in [window subviews])
    {
        UIResponder *responder = [subView nextResponder];

        //added this block of code for iOS 8 which puts a UITransitionView in between the UIWindow and the UILayoutContainerView
        if ([responder isEqual:window])
        {
            //this is a UITransitionView
            if ([[subView subviews] count])
            {
                UIView *subSubView = [subView subviews][0]; //this should be the UILayoutContainerView
                responder = [subSubView nextResponder];
            }
        }

        if([responder isKindOfClass:[UIViewController class]]) {
            return [self topViewController: (UIViewController *) responder];
        }
    }

    return nil;
}

+ (UIViewController *) topViewController: (UIViewController *) controller
{
    BOOL isPresenting = NO;
    do {
        // this path is called only on iOS 6+, so -presentedViewController is fine here.
        UIViewController *presented = [controller presentedViewController];
        isPresenting = presented != nil;
        if(presented != nil) {
            controller = presented;
        }

    } while (isPresenting);

    return controller;
}
13
nvrtd frst

Diğer tüm çözümlerden çok daha az kod:

Amaç-C versiyonu:

- (UIViewController *)getTopViewController {
    UIViewController *topViewController = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
    while (topViewController.presentedViewController) topViewController = topViewController.presentedViewController;

    return topViewController;
}

Swift 2.0 sürümü: (kredi Steve.B'ye gider)

func getTopViewController() -> UIViewController {
    var topViewController = UIApplication.sharedApplication().delegate!.window!!.rootViewController!
    while (topViewController.presentedViewController != nil) {
        topViewController = topViewController.presentedViewController!
    }
    return topViewController
}

Modeller ile bile uygulamanızın her yerinde çalışır.

10
jungledev

Her ViewController için başlık belirtin ve ardından mevcut ViewController'ın başlığını aşağıda verilen kodla alın.

-(void)viewDidUnload {
  NSString *currentController = self.navigationController.visibleViewController.title;

Sonra böyle başlığınla kontrol et

  if([currentController isEqualToString:@"myViewControllerTitle"]){
    //write your code according to View controller.
  }
}
7
Neel Kamal

zirinisp'in Swift'deki Yanıtı:

extension UIWindow {

    func visibleViewController() -> UIViewController? {
        if let rootViewController: UIViewController  = self.rootViewController {
            return UIWindow.getVisibleViewControllerFrom(rootViewController)
        }
        return nil
    }

    class func getVisibleViewControllerFrom(vc:UIViewController) -> UIViewController {

        if vc.isKindOfClass(UINavigationController.self) {

            let navigationController = vc as UINavigationController
            return UIWindow.getVisibleViewControllerFrom( navigationController.visibleViewController)

        } else if vc.isKindOfClass(UITabBarController.self) {

            let tabBarController = vc as UITabBarController
            return UIWindow.getVisibleViewControllerFrom(tabBarController.selectedViewController!)

        } else {

            if let presentedViewController = vc.presentedViewController {

                return UIWindow.getVisibleViewControllerFrom(presentedViewController.presentedViewController!)

            } else {

                return vc;
            }
        }
    }
}

Kullanımı:

 if let topController = window.visibleViewController() {
            println(topController)
        }
7
Bobj-C

Neden uygulama bildiriminde Push bildirim kodunu kullanmıyorsunuz? Doğrudan bir bakış açısıyla mı ilgili?

Bir UIViewController görünümünün şu anda görünür olup olmadığını, görünümün window özelliğinin bir değeri olup olmadığını kontrol ederek kontrol edebilirsiniz. Daha fazlası için here .

4
Dima

Benimki daha iyi! :)

extension UIApplication {
    var visibleViewController : UIViewController? {
        return keyWindow?.rootViewController?.topViewController
    }
}

extension UIViewController {
    fileprivate var topViewController: UIViewController {
        switch self {
        case is UINavigationController:
            return (self as! UINavigationController).visibleViewController?.topViewController ?? self
        case is UITabBarController:
            return (self as! UITabBarController).selectedViewController?.topViewController ?? self
        default:
            return presentedViewController?.topViewController ?? self
        }
    }
}
4
Nicolas Manzini

Sadece @ zirinisp cevabına ekleyin.

Bir dosya oluşturun, UIWindowExtension.Swift olarak adlandırın ve aşağıdaki pasajı yapıştırın:

import UIKit

public extension UIWindow {
    public var visibleViewController: UIViewController? {
        return UIWindow.getVisibleViewControllerFrom(self.rootViewController)
    }

    public static func getVisibleViewControllerFrom(vc: UIViewController?) -> UIViewController? {
        if let nc = vc as? UINavigationController {
            return UIWindow.getVisibleViewControllerFrom(nc.visibleViewController)
        } else if let tc = vc as? UITabBarController {
            return UIWindow.getVisibleViewControllerFrom(tc.selectedViewController)
        } else {
            if let pvc = vc?.presentedViewController {
                return UIWindow.getVisibleViewControllerFrom(pvc)
            } else {
                return vc
            }
        }
    }
}

func getTopViewController() -> UIViewController? {
    let appDelegate = UIApplication.sharedApplication().delegate
    if let window = appDelegate!.window {
        return window?.visibleViewController
    }
    return nil
}

Her yerde kullanın:

if let topVC = getTopViewController() {

}

@Zirinisp 'e teşekkürler.

3
Ashok Kumar S

Yukarıdaki NSNotificationCenter Post ile ilgili olarak (üzgünüm altında bir yorum nereye göndereceğinizi bulamıyorum ...)

Bazıları - [NSConcreteNotification allKeys] hatasını alıyordu. Bunu değiştir:

-(void)didReceiveRemoteNotification:(NSDictionary *)userInfo

buna:

-(void)didReceiveRemoteNotification:(NSNotification*)notif {
NSDictionary *dict = notif.userInfo;
}
3
Bseaborn
extension UIApplication {
    /// The top most view controller
    static var topMostViewController: UIViewController? {
        return UIApplication.shared.keyWindow?.rootViewController?.visibleViewController
    }
}

extension UIViewController {
    /// The visible view controller from a given view controller
    var visibleViewController: UIViewController? {
        if let navigationController = self as? UINavigationController {
            return navigationController.topViewController?.visibleViewController
        } else if let tabBarController = self as? UITabBarController {
            return tabBarController.selectedViewController?.visibleViewController
        } else if let presentedViewController = presentedViewController {
            return presentedViewController.visibleViewController
        } else {
            return self
        }
    }
}

Bu sayede üst görünüm kontrolünü kolayca alabilirsiniz.

let viewController = UIApplication.topMostViewController

Unutulmaması gereken bir şey, şu anda görüntülenmekte olan bir UIAlertController varsa, UIApplication.topMostViewController ____ 'nin bir UIAlertController döndüreceğini gösterir.

2
NSExceptional

Bu benim için çalıştı. Farklı denetleyicilere sahip birçok hedefim var, bu nedenle önceki cevaplar işe yaramadı. 

i̇lk önce bunu AppDelegate sınıfınızın içinde istersiniz:

var window: UIWindow?

o zaman, işlevinizde

let navigationController = window?.rootViewController as? UINavigationController
if let activeController = navigationController!.visibleViewController {
    if activeController.isKindOfClass( MyViewController )  {
        println("I have found my controller!")    
   }
}
2
CodeOverRide

Bu denedim ki mümkün olan en iyi yol. Eğer birine yardım edecekse ...

+ (UIViewController*) topMostController
{
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;

    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }

    return topController;
}
1
Mayur Deshmukh

Uygulamanızı hata ayıklama veya serbest bırakma ile çalıştırıyorsanız, derleme yapılandırmanızı daima kontrol edin.

ÖNEMLİ NOT: Uygulamanızı hata ayıklama modunda çalıştırmadan test edemezsiniz

Bu benim çözümümdü 

1
vikram singh

Jungledev'in cevabının Swift 2.0 sürümü

func getTopViewController() -> UIViewController {
    var topViewController = UIApplication.sharedApplication().delegate!.window!!.rootViewController!
    while (topViewController.presentedViewController != nil) {
        topViewController = topViewController.presentedViewController!
    }
    return topViewController
}
1
Steven.B

UIApplication özelliği ile visibleViewControllers için bir kategori oluşturdum. Ana fikir oldukça basittir. viewDidAppear'da viewDidDisappear ve UIViewController yöntemlerini swizzled. viewDidAppear yönteminde viewController yığına eklenir. viewDidDisappear yönteminde viewController yığından kaldırılır. Zayıf NSPointerArray başvurularını saklamak için NSArray yerine UIViewController kullanılır. Bu yaklaşım, herhangi bir viewControllers hiyerarşisi için işe yarar.

UIApplication + VisibleViewControllers.h

#import <UIKit/UIKit.h>

@interface UIApplication (VisibleViewControllers)

@property (nonatomic, readonly) NSArray<__kindof UIViewController *> *visibleViewControllers;

@end

UIApplication + VisibleViewControllers.m

#import "UIApplication+VisibleViewControllers.h"
#import <objc/runtime.h>

@interface UIApplication ()

@property (nonatomic, readonly) NSPointerArray *visibleViewControllersPointers;

@end

@implementation UIApplication (VisibleViewControllers)

- (NSArray<__kindof UIViewController *> *)visibleViewControllers {
    return self.visibleViewControllersPointers.allObjects;
}

- (NSPointerArray *)visibleViewControllersPointers {
    NSPointerArray *pointers = objc_getAssociatedObject(self, @selector(visibleViewControllersPointers));
    if (!pointers) {
        pointers = [NSPointerArray weakObjectsPointerArray];
        objc_setAssociatedObject(self, @selector(visibleViewControllersPointers), pointers, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return pointers;
}

@end

@implementation UIViewController (UIApplication_VisibleViewControllers)

+ (void)swizzleMethodWithOriginalSelector:(SEL)originalSelector swizzledSelector:(SEL)swizzledSelector {
    Method originalMethod = class_getInstanceMethod(self, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);
    BOOL didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
    if (didAddMethod) {
        class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        [self swizzleMethodWithOriginalSelector:@selector(viewDidAppear:)
                               swizzledSelector:@selector(uiapplication_visibleviewcontrollers_viewDidAppear:)];
        [self swizzleMethodWithOriginalSelector:@selector(viewDidDisappear:)
                               swizzledSelector:@selector(uiapplication_visibleviewcontrollers_viewDidDisappear:)];
    });
}

- (void)uiapplication_visibleviewcontrollers_viewDidAppear:(BOOL)animated {
    [[UIApplication sharedApplication].visibleViewControllersPointers addPointer:(__bridge void * _Nullable)self];
    [self uiapplication_visibleviewcontrollers_viewDidAppear:animated];
}

- (void)uiapplication_visibleviewcontrollers_viewDidDisappear:(BOOL)animated {
    NSPointerArray *pointers = [UIApplication sharedApplication].visibleViewControllersPointers;
    for (int i = 0; i < pointers.count; i++) {
        UIViewController *viewController = [pointers pointerAtIndex:i];
        if ([viewController isEqual:self]) {
            [pointers removePointerAtIndex:i];
            break;
        }
    }
    [self uiapplication_visibleviewcontrollers_viewDidDisappear:animated];
}

@end

https://Gist.github.com/medvedzzz/e6287b99011f2437ac0beb5a72a897f0

Swift 3 versiyonu

UIApplication + VisibleViewControllers.Swift

import UIKit

extension UIApplication {

    private struct AssociatedObjectsKeys {
        static var visibleViewControllersPointers = "UIApplication_visibleViewControllersPointers"
    }

    fileprivate var visibleViewControllersPointers: NSPointerArray {
        var pointers = objc_getAssociatedObject(self, &AssociatedObjectsKeys.visibleViewControllersPointers) as! NSPointerArray?
        if (pointers == nil) {
            pointers = NSPointerArray.weakObjects()
            objc_setAssociatedObject(self, &AssociatedObjectsKeys.visibleViewControllersPointers, pointers, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
        return pointers!
    }

    var visibleViewControllers: [UIViewController] {
        return visibleViewControllersPointers.allObjects as! [UIViewController]
    }
}

extension UIViewController {

    private static func swizzleFunc(withOriginalSelector originalSelector: Selector, swizzledSelector: Selector) {
        let originalMethod = class_getInstanceMethod(self, originalSelector)
        let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
        let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
        if didAddMethod {
            class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    }

    override open class func initialize() {
        if self != UIViewController.self {
            return
        }
        let swizzlingClosure: () = {
            UIViewController.swizzleFunc(withOriginalSelector: #selector(UIViewController.viewDidAppear(_:)),
                                         swizzledSelector: #selector(uiapplication_visibleviewcontrollers_viewDidAppear(_:)))
            UIViewController.swizzleFunc(withOriginalSelector: #selector(UIViewController.viewDidDisappear(_:)),
                                         swizzledSelector: #selector(uiapplication_visibleviewcontrollers_viewDidDisappear(_:)))
        }()
        swizzlingClosure
    }

    @objc private func uiapplication_visibleviewcontrollers_viewDidAppear(_ animated: Bool) {
        UIApplication.shared.visibleViewControllersPointers.addPointer(Unmanaged.passUnretained(self).toOpaque())
        uiapplication_visibleviewcontrollers_viewDidAppear(animated)
    }

    @objc private func uiapplication_visibleviewcontrollers_viewDidDisappear(_ animated: Bool) {
        let pointers = UIApplication.shared.visibleViewControllersPointers
        for i in 0..<pointers.count {
            if let pointer = pointers.pointer(at: i) {
                let viewController = Unmanaged<AnyObject>.fromOpaque(pointer).takeUnretainedValue() as? UIViewController
                if viewController.isEqual(self) {
                    pointers.removePointer(at: i)
                    break
                }
            }
        }
        uiapplication_visibleviewcontrollers_viewDidDisappear(animated)
    }
}

https://Gist.github.com/medvedzzz/ee6f4071639d987793977dba04e11399

0
Evgeny Mikhaylov