关于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. WLC license管理

    关于控制器的license,可以参考对应平台的Datasheet: Cisco 2504 WLC Cisco 3504 WLC Cisco 5508 WLC Cisco 5520 WLC Cisco ...

  2. 【MySQL】数据类型之数字相关

    " 目录 #. 数值类型 1. 数值范围验证 /. 有符号 /. 无符号 2. int类型显示长度验证 #. 浮点型 1. 验证 /. 建表 /. 精度 #. 日期类型 1. 验证 /. y ...

  3. 关于强化神兽(圣兽)DBC参数详解

    狗的攻击类型是114,名称.攻击类型.攻击图像.怪物样子.怪物等级.不死系.破隐身.经验值.生命值.魔法值.防御.魔防.最小攻击.最大攻击.魔法力.道术力.敏捷.准确.行走速度.一步几格.行走等待.攻 ...

  4. 批量导出存储在msdb库的SSIS包

    http://blog.51cto.com/ultrasql/1924464 use msdb go IF OBJECT_ID('msdb.dbo.usp_ExportSSISPkgs') IS NO ...

  5. DVWA实验之Brute Force(暴力破解)- Low

    DVWA实验之Brute Force-暴力破解- Low     这里开始DVWA的相关实验~   有关DVWA环境搭建的教程请参考: https://www.cnblogs.com/0yst3r-2 ...

  6. PyQt5信号与槽详解

    1.信号与槽函数基础'''信号与槽函数基础,信号是一个事件,发射信号之后槽函数就会执行'''from PyQt5.QtWidgets import *import sys class signal(Q ...

  7. Cisco AP-Sniffer模式空口抓包

     第一步:WLC/AP侧 配置AP为sniffer模式: 配置提交后,AP会重启,并且将不能发出SSID为clients提供服务. 第二步:一旦AP重新加入WLC,配置AP抓取的信道和抓取后的数据包发 ...

  8. VSCODE 教程网

    http://geek-docs.com/vscode/vscode-tutorials/vs-code-text-selection.html

  9. 利用ProxySQL实现MySQL的读写分离

    本文简单介绍ProxySQL的安装及如果实现后端MySQL主从结构的读写分离. 一.ProxySQL安装 Proxy官方地址:https://proxysql.com/ proxysql-2.0.8- ...

  10. python浅谈编程规范和软件开发目录规范的重要性

    前言 我们这些初学者,目前要做的就是遵守代码规范,这是最基本的,而且每个团队的规范可能还不一样,以后工作了,尽可能和团队保持一致,目前初学者就按照官方的要求即可 新人进入一个企业,不会接触到核心的架构 ...