我是从今年的10月份,也就是Xcode11版本开始接触iOS开发的,因此对于各个版本之间的差异了解的不多,开始接触iOS开发也是从iOS13版本开始的,在自测过程中,发现了工程版本不能向下兼容的问题,相应的原因与解决办法,已经在我的其他文章中有所提及,而且正在慢慢补充的过程中,如果有大佬看到文章中的错误,请及时与我联系,谢谢!
之前做过C#的客户端和asp.net的项目,感觉iOS应该也有类似于控件的拖拽功能,要不然时刻计算坐标位置岂不是太麻烦。终于功夫不负有心人,最终找到了控件的位置。如图
既然说到这里了,这里就介绍一下利用mainStoryboard的button实现页面跳转的功能,通过这种方式形成的新页面,无需写一些关于回退的功能,这是它的优点。
有优点,必定对应有缺点,毕竟偷懒的方式实现的功能,多多少少都会存在一些解决不了的问题,缺点我们后面介绍,先说说如何去实现这个页面跳转的(其实我记得这块我都写过了。。。可是怎么样也找不到在哪里写的了。。。那就再写一次),好了废话不多说。
双击后,在Storyboard中会生成一个新的ViewController,然后在主ViewController中添加一个button。
选中button,按住control键,拖拽到如图所示位置,然后选择相应的显示方式即可。
如图所示
这里我选择的是show的方式,其他方式也可以选择,只不过show在iOS13里面用的普遍,后面会介绍一下页面跳转的不同与改变。这样,一个简单的页面跳转和跳回功能就实现了,就不在这里演示了,因为这个太简单了。自己操作一次就可以了。
一个ViewController对应着一对相应的.m/.h文件,设置方式如下,首先新建一个类,继承自UIVIewController,然后在Storyboard中设置。
这样就可以在secondViewController.m文件中控制对应的页面中控件。
创建点击后的action动作,然后在里面写相应的功能就可以了。
由于Xcode的不断进化,曾经的方法presentModalViewController已经弃用。
[self presentModalViewController:<#(nonnull UIViewController *)#> animated:<#(BOOL)#>];
当前采用的页面跳转方法是下边两种
//方法一
[self.navigationController pushViewController:vc animated:YES];
//方法二
[self presentViewController:vc animated:YES completion:nil];
接下来将分别介绍一下两种跳转方法的不同,以及在不同情况下的ViewController的初始化。
分为三种情况:
secondViewController *vc = [[secondViewController alloc]init];
[self.navigationController pushViewController:vc animated:YES];
secondViewController *vc = [[secondViewController alloc]initWithNibName:@"secondViewController" bundle:nil];
[self.navigationController pushViewController:vc animated:YES];
secondViewController *vc = [[UIStoryboard storyboardWithName:@"secondViewController"
bundle:nil] instantiateInitialViewController];
[self.navigationController pushViewController:vc animated:NO];
同样分为三种情况:
secondViewController *vc = [[secondViewController alloc]init];
[self presentViewController:control animated:YES completion:nil];
secondViewController *vc = [[secondViewController alloc]initWithNibName:@"secondViewController" bundle:nil];
[self presentViewController:control animated:YES completion:nil];
secondViewController *control = [self.storyboard instantiateViewControllerWithIdentifier:@"secondViewController"];
[self presentViewController:control animated:YES completion:nil];
方法一的回退方式,可以自行百度一下,因为push进来的,采用pop就可以返回去,毕竟是个压栈的操作方式。
这里着重分享一下方法二的回退,假如说从页面A preset 到页面B 再 preset 到页面C ,如果想回到页面A ,只需要执行下面这条语句就可以了。
[self.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
这个可以说是最简单的回退了,present了几个就presenting几个就可以了。有关present于dismiss的详细介绍可以参考这篇文章:你真的了解iOS中控制器的present和dismiss吗?
在iOS 13之前,我们模态展示的视图默认是全屏的,而在iOS13中,默认的样式变成了类iPhone上safari的分页样式:
而在低于iOS13版本的系统中,并不支持这种展示效果。这就是前面提及到的show的展示方式,在低于iOS13(后面统称低版本)的手机中,还是以全屏的效果显示。
在使用 presentViewController 来跳转视图时系统提供了两个参数来简化跳转的设置,modalTransitionStyle 和 modalPresentationStyle。前者为转场过渡的类型,后者为展示的样式,系统为两者都提供了多种可选样式。
modalPresentationStyle(该属性是控制器在模态视图时将要使用的样式)没有设置需要的类型。在iOS13中modalPresentationStyle的默认改为UIModalPresentationAutomatic,而在低版本中默认是UIModalPresentationFullScreen。
另外补充一下其他的几种状态
UIModalPresentationFullScreen:代表弹出VC时,presented VC充满全屏,如果弹出VC的wantsFullScreenLayout设置为YES的,则会填充到状态栏下边,否则不会填充到状态栏之下。
UIModalPresentationPageSheet:代表弹出是弹出VC时,presented VC的高度和当前屏幕高度相同,宽度和竖屏模式下屏幕宽度相同,剩余未覆盖区域将会变暗并阻止用户点击,这种弹出模式下,竖屏时跟UIModalPresentationFullScreen的效果一样,横屏时候两边则会留下变暗的区域。
UIModalPresentationFormSheet:这种模式下,presented VC的高度和宽度均会小于屏幕尺寸,presented VC居中显示,四周留下变暗区域。
UIModalPresentationCurrentContext:这种模式下,presented VC的弹出方式和presenting VC的父VC的方式相同。
这四种方式在iPad上面统统有效,但在iPhone和iPod touch上面系统始终已UIModalPresentationFullScreen模式显示presented VC。
在工程中,由于模型的加载与卸载分别放置在了viewWillAppear与viewWillDisappear中,在页面即将加载或即将消失的时候,这两个方法里面的内容会自动调用,因此,这个模型的加载与卸载跟页面的生命周期紧密的联系起来。
在iOS13及以上系统中,采用刚刚默认的方式,即UIModalPresentationAutomatic方式加载的页面,A 进入 B后,A页面会挂起,不会执行viewWillDisapper,但是在低版本中,默认的是UIModalPresentationFullScreen,出现了模型的卸载,这个问题没有查找到什么原因,初步认为,在低版本中,当前的A页面被B页面覆盖掉,系统认为当前页面已经Disappear了。
这个问题相当的棘手,因为设置UIModalPresentationAutomatic的话,低版本的系统会报错,没有这个枚举类型。因此采用根据手机系统是否为iOS13版本为界限,调用不同的方法。
解决方法:
iOS13及以上的版本仍采用present方法,低版本系统,采用加载子视图的方式来实现页面生命周期的维持,同时加载下一个页面的功能,但是这个方法的使用中,一定要切记,父级视图一定不要有任何UI刷新的操作,放置内存占用率过高。
secondImageViewController *control = [self.storyboard instantiateViewControllerWithIdentifier:@"secondImageViewController"];
if (@available(iOS 13.0, *)){
[self presentViewController:control animated:YES completion:nil];
} else {
control.view.frame = self.view.bounds;
[self.view addSubview:control.view];
[self addChildViewController:control];
}
//页面回退,删除子视图就可以了。
[self.view removeFromSuperview];
至此,这个问题可以说是规避掉了。