首先介绍下开源的第三方库MBProgressHUD
一个很好的实现了加载提示框的第三方demo。广泛用于应用中。
简单看下界面
开源地址:https://github.com/jdg/MBProgressHUD
好了,本文不是介绍如何使用它。
主要说下 我在使用这斯货时遇到一个怪异问题,然后引发出的一点自我解释,或许你也会遇到的一个问题。
我们先来看下demo给的一个简单例子
- (IBAction)showSimple:(id)sender {
// The hud will dispable all input on the view (use the higest view possible in the view hierarchy)
HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
[self.navigationController.view addSubview:HUD];
// Regiser for HUD callbacks so we can remove it from the window at the right time
HUD.delegate = self;
// Show the HUD while the provided method executes in a new thread
[HUD showWhileExecuting:@selector(myTask) onTarget:self withObject:nil animated:YES];
}
注意HUD是根据我们传递进去的View来实例化的(准确的说是我们实例化HUD时定义frame是根据传递进的view来生成同样大小)。
简单来说,整个HUD其实是一个父布局一样大小的类似于背景的VIew,然后才是中心那个黑色的提示框。
其实这样的设计是做一个人为的同步,在加载期间做一个人为的同步。也就是事件处理完以前,你做了交互操作。
很多时候我们确实需要这样的设计,即,在网络请求活着是用户事件返回结果前,不允许用户操作。
说一个我实际中碰到的例子:
在做上一个Android项目时,有一个金额支付跳转到支付宝的操作。
在点击确认后,会将表单信息传递到我们的服务端生成订单信息和支付金额返回,然后跳转到支付宝。
如果我们将这个操作看成是在ios执行,我点一次确认,网络请求发出,然后如果没有屏蔽用户的交互,我手贱在返回数据跳转到支付宝前又点了一次,
那你就一个货物就可能买了两次,或者一些其他的支付异常。(这确实是我android产品中遇到的,虽然android本身的dialog机制是屏蔽了其他交互的,
但是android蛋疼的存在一个back,取消dialog的按钮,因此还是会造成多次提交的问题,当然最后是进一步屏蔽掉dialog的取消事件)。
也就是总体来说,我们需要一层加载框来屏蔽交互。
对于ios中,这一层就是我们这样
[self.navigationController.view addSubview:HUD];
因此就出现我标题所提到的一个问题了。
我的意思想屏蔽导航栏的回退。
因此我会需要frame大小理论上是self.navigationController.view大小。
于是就很顺手的传递进将其传递进去。
但是,当我从前一个界面跳转到这个界面,进行第一次加载时,会报错"View must not be nil."
什么情况!!
demo 翻来翻去,他就是这么写的啊。
然后再看一下我的流程,
在viewDidLoad中所有都初始化加载完后,调用了网络请求,然后去实例化hud。
然后我又去degub下了,发现self.navigationController居然是空的~~
就是说此刻我这个视图控制器还没有拥有对导航控制器的引用~
突然就觉得好奇怪,那我等会会用到self.navigationController push到下一个控制器,又说明它是存在的了。
因此简单猜想下整个流程机制问题:
1.我从前一个视图推push当前视图时,先实例化然后加载该控制器的所有UI界面,将这整体放入视图控制器栈中(理论上也就是成了栈顶视图控制器)。
2.导航栏控制器将这个top视图添加到window上,把自身指针传给这个top视图,使其获得导航引用以及控制权。
简单来说,viewdidload只是加载初始化了所有视图。然后添加到导航控制视图栈中,然后将其当做顶端视图控制器添加到window上
(猜测,但是大致意思应该就是这样),赋予navigationController的引用控制权。因此此刻才self.navxxxx被赋值了。
然后根据控制器的生命周期,因为我们知道,把视图的显示就是一个控制器将视图添加到window上的过程和结果。
在这一步中,视图控制器会调用viewWillAppear,以及didapp~~。
然后我重载测试后,此刻nav已经被赋值。
这也就是说,此刻你调用网络请求,hud实例化时nav不会再被报空。
说了这么多,其实真正的意思只是对导航控制的工作原理做一个自我的感性认识。
因为貌似在此之前,我还真么仔细去理解控制器,视图栈是如何运作的,而是机械性的看了simpleCode,
就说,哦,我知道这个控件啊,不就这么用么。
同样希望对一些碰到和我同样的异常的朋友有所帮助。
以上可能只是我自己对自己的一个解释,更多真实内容请参考官方文档。