• 导航栏协议方法UINavigationControllerDelegate


    关于UINavigationControllerDelegate:

    • Delegate中一共有6个方法。其中两个跟控制器ViewController的跳转有关、有两个跟屏幕的旋转有关、有两个跟导航栏动画有关(可以设计交互式或者非交互式的转场动画)。

     前提配置:为了下面所说的测试都能如期的进行,有几个步骤是需要设置好的

    1、声明UINavigationControllerDelegate协议

    @interface ViewControllerOne () <UINavigationControllerDelegate>

    2、遵守该协议

    self.navigationController.delegate = self;

    3、在遵守该协议的控制器中写出需要用到的协议方法


    一、首先介绍下跟控制器的跳转相关的两个协议方法:

    // Called when the navigation controller shows a new top view controller via a push, pop or setting of the view controller stack.
    - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
        NSLog(@"~~~~~~~~~~willShowViewController");
    }
    
    - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
        NSLog(@"~~~~~~~~~~didShowViewController");
    }

    说明:

    1、当控制器push、pop、直接设置navigationController的controllers属性,都是可以触发这两个方法的。

    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        
        ViewControllerTwo *vcTwo = [[ViewControllerTwo alloc] init];
        
        // 可触发
        [self.navigationController pushViewController:vcTwo animated:YES];
        
        /* 不可触发
        [self.view addSubview:vcTwo.view];
        [self addChildViewController:vcTwo];
        [vcTwo didMoveToParentViewController:self];
        */
        
        /* 不可触发
        [self presentViewController:vcTwo animated:YES completion:nil];
        */
        
        /* 可触发
        self.navigationController.viewControllers = @[self, vcTwo];
        */
    }

    2、为了能够准确的理解这两个方法,一定要记住这个是navigationController的协议方法。对它来说,即将进入这个控制器栈时调用willShow方法,已经进栈后调用didShow方法。

    当vc1-push-vc2时,是vc2willShow、vc2didShow,

    当vc2-pop-vc1时,是vc1willShow、vc1didShow。

    3、因为navigationController自身、凡是进栈后的控制器都能够拿到navigationController这个对象,因此都可以成为它的代理。但是,有两个原则:

    (1)始终以最新成为代理的为准。

    (2)当最新成为代理的控制器销毁后(因为代理是weak,所以不会强留代理),第二新的代理成为接班者。

    但是有个注意点:一个控制器销毁是在另一个控制器didShow之后,一个控制器成为接班者是在didShow之后。

    举例如下:vc1、vc2都是navigationController的代理。过程是vc1-push-vc2,然后vc2-pop-vc1。

    vc1-push-vc2的过程是:vc1是真代理、vc2willShow、vc2didshow、vc2成为真代理。

    vc2-pop-vc1的过程是:vc2是真代理、vc1willShow、vc1didShow、vc1成为真代理。


    二、然后介绍下跟屏幕的旋转有关的代理(真的不常用,而且真的比较坑)

    首先要说明白的是,屏幕旋转有三个相关的地方:手机上的旋转开关、项目在Xcode上的配置、接下来要介绍的这2个协议方法。

    // 返回-导航控制器支持的设备方向
    // 每次旋转设备的时候询问(前提是iPhone上的屏幕旋转开关是开着的)
    - (UIInterfaceOrientationMask)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController {
        NSLog(@"~~~~~设置方法设置导航控制器支持的设备方向~~~~~");
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }
    
    // 这个方法设置导航控制器的首选设备方向
    - (UIInterfaceOrientation)navigationControllerPreferredInterfaceOrientationForPresentation:(UINavigationController *)navigationController {
        NSLog(@"~~~~~这个方法设置导航控制器的首选设备方向~~~~~");
        return UIInterfaceOrientationLandscapeLeft;
    }

    现在表述下手机上的旋转开关、Xcode上的配置、协议方法、屏幕的方向四者之间的联系:

    (1)当手机上的旋转开关关闭时,Xcode上的配置失效、当设备旋转时协议方法不调用、屏幕只能是竖屏显示。

    (2)当手机上的旋转开关开着时,屏幕的可旋转方向由「Xcode上的配置」和「可旋转方向的协议方法」两者的交集决定。当设备旋转时,「可旋转方向的协议方法」被调用,屏幕会旋转成交集中存在的方向。

    (3)至于屏幕最初显示的方向的依据现象是这样的:只要「Xcode上的配置」,包含Portrait方向(即竖屏),则最初显示的方向都是竖屏。只要「Xcode上的配置」不包含Portrait(即竖屏),则最初显示的方向就是设备往左(即屏幕往右)的方向(可以通过下面图像进行理解)。至于「首选设备方向的协议方法」一直不调用。在这种情况下,无关手机上的旋转开关的状态(不管开关,前面文字描述的内容依然成立)。

     吐槽:

    (1)虽然Xcode上的配置写的是“Device Orientation”,但是真实功能却是“可选方向”的作用。并且真实的可选方向,还必须是「Xcode上的配置」和「可旋转方向协议方法」两者的交集。

    (2)「首选设备方向的协议方法」一直不被调用。


    三、简介下跟导航栏转场动画相关的两个协议方法

    // 没有交互的转场动画
    - (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                      animationControllerForOperation:(UINavigationControllerOperation)operation
                                                   fromViewController:(UIViewController *)fromVC
                                                     toViewController:(UIViewController *)toVC {
        NSLog(@"~~~~~~~~~~%ld~%@~%@", operation, fromVC.class, toVC.class);
        return nil;
    }
    
    // 有交互的转场动画
    - (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
                             interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController {
        NSLog(@"~~~~~~~~~~%@", animationController);
        return nil;
    }

    免责说明:

    关于转场动画,不在该篇文章的讨论范围。其实也是因为内容比较多,后面在专门重起一文再议。

    简单闲扯下:

    1、转场动画可以分为交互式与非交互式,如果设置非交互式的用上面第一个协议方法就可以了。

    2、第一个协议方法中的operation参数,可以知道当前进行的是push还是pop操作。

  • 相关阅读:
    清北学堂模拟赛d6t1 角谷猜想
    清北学堂模拟赛d4t1 a
    清北学堂模拟赛d3t6 c
    清北学堂模拟赛d3t5 c
    清北学堂模拟赛d3t4 a
    清北学堂模拟赛d3t3 c
    清北学堂模拟赛d3t1 a
    清北学堂模拟赛d2t3 逆序对(pair)
    Android(java)学习笔记176: 远程服务的应用场景(移动支付案例)
    Android(java)学习笔记175:Android进程间通讯(IPC)之AIDL
  • 原文地址:https://www.cnblogs.com/cchHers/p/9104964.html
Copyright © 2020-2023  润新知