IOS 学习笔记 页面跳转和页面导航
目录
2.1.6 将“下一页”按钮和和第二页关联起来,点击后能够跳转
2.1.7 Main.storyboard上的页面和具体类绑定
上一章笔记中记录了NavigationBar的简单使用,并没有真正的使用它做页面之间的跳转,这里说说的页面跳转不是类似Android的Fragment之间的跳转,而是类似于Android中的从Activity跳转到另一个Activity,这一章将记录学习页面件跳转的内容。
Cocoa Touch遵循了MVC的模式,这里学习的页面间的跳转也就是官方所说的导航,从一个View Controller到另一个View Controller。
视图控制器又很多种类,其中不仅能够显示视图,也就是用户界面,也起到导航的作用。
1 导航模式的种类
1.1 平铺式导航
平铺式导航有分屏和分页,在内容上是没有层级关系的,展示的内容都放在一个屏幕中,可以左右或者上下滑动,如:
1.2 标签式导航
将应用按照功能划分为多个功能模块,彼此之间独立,通过tab来切换各个功能模块,如下图:
1.3 树形结构式导航
属性结构的导航模式类似树形结构,分为枝叶,那些树叶属于那个枝干,是有层级俄关系的,典型的树形结构导航就是邮箱,如下图:
2 视图控制器的种类
视图控制器 | 视图控制器的在导航上的作用 |
UIViewController | 可用于自定义视图控制器的导航,用于界面间的跳转,比如用一个UIViewController控制另外2个UIViewController工作。 |
UINavigationController | 导航控制器,可以与UITableViewController结合使用, |
UITabBarController | 标签栏控制器,可用于构建标签式导航模式 |
UIPageViewController | 电子书风格的导航控制器,主要用电子书和电子杂志类的应用开发,是IOS最近才推出的。 |
UISplitViewController | 主要用于ipad应用开发,分割屏幕风格的视图控制器 |
UIPopoverController | 主要用于ipad应用开发,气泡风格的控制器 |
2.1 使用UIViewController实现页面跳转
2.1.1 布局第一个页面
首先在故事板的View Controller的顶部添加一个NavigationBar,中间添加一个Label,如下图:
2.1.2 调出Navigation Controller
故事板中选中 View Controller > 标题栏 Editor > Embed In > Navigation Contoller,调出Navigation Controller,如下图
2.1.3 给导航栏添加一个标题
2.1.4 给NavigationBar添加跳转按钮
然后给NavigationBar 右边加一个跳转按钮 文案“下一页”
2.1.5 添加第二个页面
从视图对象库中拖拽一个View Controller放入故事板中,并重复第二步骤中的方法,调出Navigation Controller
2.1.6 将“下一页”按钮和和第二页关联起来,点击后能够跳转
按住contrl键,点击“下一页”按钮拖拽到第二个 Navigation Controller,也就是第二个控制器,弹出对话框选中show,然后可以看到中间生成了一个带圆圈的箭头,
上面gif图演示了将两个场景关联的过程,然后生成下面图的关系,注意蓝色的框是Navigation Controller和自己View Controller的联系,这个是内在的,红色的框表示两个场景的关联,这样4个Controller就关联起来了。
然后给第二个界面的NavigationBar左侧添加一个返回按钮,并将这个按钮用同样的方法和第一个Navigation Contoller关联起来买就会出翔下面的折线箭头,意思是点击返回,回到第一个界面
注意下面红色方框中的箭头,表示是进入的第一个界面,如果我们在运行后发现界面是黑屏,肯定是这一个没有设置,这篇笔记的这个列子这箭头一定是从下面开始的,如果没有设置,记得选中进入的Controller,把右边的IS Initial View Controller勾选上,这里类似与Android中的清单文件中设置某一个Activity为启动页面一样。
2.1.7 Main.storyboard上的页面和具体类绑定
Main.storyboard上的每一个界面都需要有一个UIViewController与之对应,所以我们需要创建一个SecondViewController类,并让它和第二个页面关联起来。
紧接着将联故事板中的Pager和类关联起来,接下来关联的是SecondViewController
2.1.8 具体代码
第一个页面的类都是xcode生成的没有任何改动
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
@end
第二个页面的类基本也是xcode生成的,只是手动增加了一个UILabel,其实也可以直接在Interface Builder里面拖拽生成,这里只是为了验证是否有作用,是否可以在里面编辑第二个界面。
#import "SecondViewController.h"
@interface SecondViewController ()
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 124, 120, 30)];
label.text = @"第二个页面";
[self.view addSubview:label];
}
@end
2.1.9 测试效果图
点击“下一页”,进入第二个页面,点击“返回”回到第一个页面
3 纯代码实现页面间跳转
上面通过拖拽的方式很简单直观的学习了使用Navigation Controller 控制多个View Controller相互跳转,首先能够有可以下手的兴趣,那么问题来了,不是所有的时候都通过这种方式来做跳转,有时候也会只使用代码来做。使用纯代码实现起来,就稍许有点麻烦了。
3.1 xib布局页面,实现页面见跳转
这里有个新需求需要完成,将上面故事板对应的界面使用xib分解成两个独立的存在,也就是一个xib对应一个界面,和自己的类相关联,然后做到上面相同的效果,不知道怎么使用xib布局的同学可以移步《IOS 学习笔记 使用xib文件构建界面》先看看看怎么操作。
这里遇到个问题,只是在xib中布局后往对应的ViewController拖拽生成一个
@property (weak, nonatomic) IBOutlet UIBarButtonItem *nextButton;居然会报错,错误如下,目前卡住了,网上的方法都不好使:
2019-04-19 22:15:21.875193+0800 ControllerSimple[44628:1688645] libMobileGestalt MobileGestalt.c:890: MGIsDeviceOneOfType is not supported on this platform.
2019-04-19 22:15:21.951738+0800 ControllerSimple[44628:1688645] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<UIViewController 0x7ffbe1505c30> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key nextButton.'
*** First throw call stack:
(
0 CoreFoundation 0x000000010cd181bb __exceptionPreprocess + 331
1 libobjc.A.dylib 0x000000010c2b6735 objc_exception_throw + 48
2 CoreFoundation 0x000000010cd17d29 -[NSException raise] + 9
3 Foundation 0x000000010bce1de4 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 292
4 UIKitCore 0x000000010f558292 -[UIViewController setValue:forKey:] + 87
5 UIKitCore 0x000000010f7ef573 -[UIRuntimeOutletConnection connect] + 109
6 CoreFoundation 0x000000010cd03cfd -[NSArray makeObjectsPerformSelector:] + 317
7 UIKitCore 0x000000010f7ec2b9 -[UINib instantiateWithOwner:options:] + 1814
8 UIKitCore 0x000000010f55f452 -[UIViewController _loadViewFromNibNamed:bundle:] + 383
9 UIKitCore 0x000000010f55fddc -[UIViewController loadView] + 177
10 UIKitCore 0x000000010f5600ee -[UIViewController loadViewIfRequired] + 175
11 UIKitCore 0x000000010f560940 -[UIViewController view] + 27
12 UIKitCore 0x000000010fbb7c53 -[UIWindow addRootViewControllerViewIfPossible] + 122
13 UIKitCore 0x000000010fbb836e -[UIWindow _setHidden:forced:] + 294
14 UIKitCore 0x000000010fbcb5c0 -[UIWindow makeKeyAndVisible] + 42
15 ControllerSimple 0x000000010b998601 -[AppDelegate application:didFinishLaunchingWithOptions:] + 545
16 UIKitCore 0x000000010fb76bde -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 280
17 UIKitCore 0x000000010fb785cb -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 3979
18 UIKitCore 0x000000010fb7dc2f -[UIApplication _runWithMainScene:transitionContext:completion:] + 1623
19 UIKitCore 0x000000010f39c4e9 __111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke + 866
20 UIKitCore 0x000000010f3a529c +[_UICanvas _enqueuePostSettingUpdateTransactionBlock:] + 153
21 UIKitCore 0x000000010f39c126 -[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:] + 233
22 UIKitCore 0x000000010f39cae0 -[__UICanvasLifecycleMonitor_Compatability activateEventsOnly:withContext:completion:] + 1085
23 UIKitCore 0x000000010f39acb5 __82-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:]_block_invoke + 795
24 UIKitCore 0x000000010f39a95f -[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:] + 435
25 UIKitCore 0x000000010f39fa90 __125-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:]_block_invoke + 584
26 UIKitCore 0x000000010f3a080e _performActionsWithDelayForTransitionContext + 100
27 UIKitCore 0x000000010f39f7ef -[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:] + 221
28 UIKitCore 0x000000010f3a493a -[_UICanvas scene:didUpdateWithDiff:transitionContext:completion:] + 392
29 UIKitCore 0x000000010fb7c44e -[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 515
30 UIKitCore 0x000000010f720d09 -[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 357
31 FrontBoardServices 0x00000001182d12da -[FBSSceneImpl _didCreateWithTransitionContext:completion:] + 448
32 FrontBoardServices 0x00000001182dc443 __56-[FBSWorkspace client:handleCreateScene:withCompletion:]_block_invoke_2 + 271
33 FrontBoardServices 0x00000001182dbb3a __40-[FBSWorkspace _performDelegateCallOut:]_block_invoke + 53
34 libdispatch.dylib 0x000000010e616602 _dispatch_client_callout + 8
35 libdispatch.dylib 0x000000010e619b78 _dispatch_block_invoke_direct + 301
36 FrontBoardServices 0x0000000118310ba8 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 30
37 FrontBoardServices 0x0000000118310860 -[FBSSerialQueue _performNext] + 457
38 FrontBoardServices 0x0000000118310e40 -[FBSSerialQueue _performNextFromRunLoopSource] + 45
39 CoreFoundation 0x000000010cc7d721 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
40 CoreFoundation 0x000000010cc7cf93 __CFRunLoopDoSources0 + 243
41 CoreFoundation 0x000000010cc7763f __CFRunLoopRun + 1263
42 CoreFoundation 0x000000010cc76e11 CFRunLoopRunSpecific + 625
43 GraphicsServices 0x00000001153101dd GSEventRunModal + 62
44 UIKitCore 0x000000010fb7f81d UIApplicationMain + 140
45 ControllerSimple 0x000000010b9983b0 main + 112
46 libdyld.dylib 0x000000010e68c575 start + 1
47 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
最关键的一句话是:this class is not key value coding-compliant for the key nextButton,我就纳闷了,不可能有重复的引用,就是无法通过,目前正在处理中... ...