关于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操作。

导航栏协议方法UINavigationControllerDelegate的更多相关文章

  1. Android (争取做到)最全的底部导航栏实现方法

    本文(争取做到)Android 最全的底部导航栏实现方法. 现在写了4个主要方法. 还有一些个人感觉不完全切题的方法也会简单介绍一下. 方法一. ViewPager + List<View> ...

  2. zblog插件增加后台导航栏的方法

    有时我们经常需要对插件进行设置,但是又不能让用户去做这些,那么下面的方法将会给插件增加在后台导航栏显示的功能 首先打开对应插件的文件夹,找到对应插件的  include.php  文件 将下面的代码粘 ...

  3. <iOS 导航栏>第一节:导航栏透明方法实现代码

      说下导航栏的透明方法:   很多应用需要导航栏随着向上滑动,逐渐从透明变成不透明,很炫酷,大部分应用都在使用导航栏渐变效果,现附上代码然后直接将实现,一会讲下如何来实现,这一部分直接上代码.   ...

  4. UIView显示时遮挡导航栏的方法

    [self.navigationController.view:addSubview];

  5. CSS 导航栏

    实例: 导航栏 Home News Articles Forum Contact About 导航栏 熟练使用导航栏,对于任何网站都非常重要. 使用CSS你可以转换成好看的导航栏而不是枯燥的HTML菜 ...

  6. NavUtils【底部虚拟导航栏工具类】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 获取底部虚拟导航栏的高度值 效果图 代码分析 checkDeviceHasNavigationBar(Context context ...

  7. JS写的二级导航栏(利用冒泡原理)

    今天给大家分享一种用JS写的导航栏,虽然我们工作中不会使用JS来做导航栏,为了练习我们用JS来做一个JS导航栏 这种方法要比其他方法代码量少很多,但是需要对事件冒泡有一定的理解,如果需要理解冒泡可以参 ...

  8. Flutter - 创建底部导航栏

    之前写过的一篇文章介绍了 Flutter - 创建横跨所有页面的侧滑菜单, 这次就一起来学习一下底部导航栏. 底部导航栏在ios平台上非常常见,app store就是这样的风格.还有就是大家最常用的微 ...

  9. CSS04--对齐、 布局、导航栏

    我们接着上一章,继续学习一些有关对齐.布局.导航栏的内容. 1.水平块对齐:    1.1 margin:把左和右外边距设置为 auto,规定的是均等地分配可用的外边距.结果就是居中的元素    .c ...

随机推荐

  1. appium常用的类库、对应的方法和属性

    1.driver.swipe(self, start_x, start_y, end_x, end_y, duration=None) tart_x - 滑动开始x轴坐标 start_y - 滑动开始 ...

  2. centos7.5下安装jenkins

    最近从头搭建了一套python+selenium+pytest+allure+Jenkins的环境,虽然网上挺多的,不过还是记录下来,毕竟坑还是挺多的....... 先从搭建jenkins开始把! 方 ...

  3. python、js实现WGS84、高德(火星)、百度坐标转换

    在日常工作学习中常会涉及到WGS84.高德(火星/谷歌).百度三种空间坐标系的坐标转换,本文将通过python.js两种语言实现坐标系的转换. 坐标系说明: wgs84:为一种大地坐标系,也是目前广泛 ...

  4. ASP.NET Core搭建多层网站架构【1-项目结构分层建立】

    2020/01/26, ASP.NET Core 3.1, VS2019 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构[1-项目结构分层建立] 文章目录 此分支项目代码 ...

  5. 浅谈SQL注入漏洞以及防范策略

    --HeShiwei 2014-5-15 什么是SQL注入 SQL注入,指的是用户通过向登录框输入恶意字符,利用代码的字符串拼接漏洞进行网站注入攻击,最终导致整个网站用户表信息泄露的攻击方式.黑客就是 ...

  6. JDBC 通过读取文件进行初始化

  7. SpringBoot与Mybatis整合(包含generate自动生成代码工具,数据库表一对一,一对多,关联关系中间表的查询)

    链接:https://blog.csdn.net/YonJarLuo/article/details/81187239 自动生成工具只是生成很单纯的表,复杂的一对多,多对多的情况则是在建表的时候就建立 ...

  8. idea使用vue项目

    https://blog.csdn.net/qq_42564846/article/details/82688266

  9. 使用Dotfunsctor

    设置Disable Control Flow.Disable Renaming.Disable String Encryption 为no,no为开启该功能 设置加密后输出的路i经 选择需要加密的ex ...

  10. Attributes for Slot

    关于AP Config中的一些参数的意义: Radio Type................................... RADIO_TYPE_80211ac-5 Radio Subba ...