【问题标题】:How do I know in AppDelegate when UIViewController transit to another UIViewController?当 UIViewController 转换到另一个 UIViewController 时,我如何在 AppDelegate 中知道?
【发布时间】:2018-03-25 07:41:12
【问题描述】:

在 AppDelegate 中是否知道在 AppDelegate 和 UIViewController 中没有调用任何额外方法就推送了新的 UIViewController?

AppDelegate 是否能够在不编写任何代码特别是 UIViewController 的情况下知道正在推送哪个新 UIViewController?

【问题讨论】:

  • ViewControllers 从导航控制器拥有的各自导航堆栈中被推送和弹出。 AppDelegate 只是 UIApplication 对象生命事件的委托。它们根本不相关你想达到什么目的??
  • 真的不用调用任何额外的方法吗?

标签: ios objective-c uiviewcontroller appdelegate


【解决方案1】:

好吧,我有一个 hacky 方式供您使用,因为您不想在视图控制器中编写任何代码。在下面为您查看我的类别

UINavigationController+PushNotifier.h

#import <UIKit/UIKit.h>

@interface UINavigationController (PushNotifier)
extern void PJSwizzleMethod(Class cls, SEL originalSelector, SEL swizzledSelector);

@end

UINavigationController+PushNotifier.m

#import "UINavigationController+PushNotifier.h"
#import <objc/runtime.h>


@implementation UINavigationController (PushNotifier)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        PJSwizzleMethod([self class],
                        @selector(pushViewController:animated:),
                        @selector(pj_pushViewController:animated:));
    });
}

- (void)pj_pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    //notify your Application Delegate
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ViewControllerWillPush" object:nil userInfo:@{@"pushingViewController":viewController}];
    return [self pj_pushViewController:viewController animated:animated];
}

@end

void PJSwizzleMethod(Class cls, SEL originalSelector, SEL swizzledSelector)
{
    Method originalMethod = class_getInstanceMethod(cls, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);

    BOOL didAddMethod =
    class_addMethod(cls,
                    originalSelector,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));

    if (didAddMethod) {
        class_replaceMethod(cls,
                            swizzledSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod);
    }
}

注意:这仅在您使用导航控制器和推送/显示视图控制器时才有效

【讨论】:

    【解决方案2】:

    没有适当的方法可以做到这一点,但作为一种解决方法,您可以使用此方法:

    func application (_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        guard let vc = (window?.rootViewController?.presentedViewController) else {
            return .portrait // your default orientation, to update according to your needs
        }
        if (vc.isKind(of: NSClassFromString("The class you are looking to")!)) {
    // Here you can put any code you want, your view controller was just pushed
            return .allButUpsideDown
        }
        return .portrait
     //   return the orientation you want
    }
    

    问题是你需要在你的应用中为每个 viewController 做一个演员,做一些自定义代码会更干净,更适合你的需要。

    【讨论】:

    • 您的解决方案如何检测应用程序中是否推送了任何视图控制器,就像问题中提出的那样?
    • @AuRis 如果你施放成功,这意味着你的视图控制器刚刚被推送,我认为这很清楚:/
    • 首先你的代码不能编译,因为你少了一个大括号。其次,如果您需要检查每个可能的类,我什至不会称其为解决方法。最重要的是,如果转换成功并不意味着视图控制器被推送。
    • 我的错,我删除了一些代码并忘记检查它。另一方面,代码正在执行所要求的操作,我用它来知道我的 videoPlayer 何时在屏幕上。如果不使用自定义方法,在 appDelegate 中没有其他方法可以做到这一点。你无聊吗?因为你看起来很有攻击性。
    • 哈哈老兄,我只是指出您的代码没有提供答案的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多