内容简介:在项目早期开发阶段,还不需要接入后台网络数据,主要工作的界面的开发。 随着业务页面的深入,要查看二级、三级页面的效果就需要编译后跳转两三次甚至更多,不断地重复这个过程相对来说,就没有可以直接启动就查看那个页面来得那么高效。常见的做法是在application:didFinishLaunchWithOptions:时直接push到想要到达的页面,如下:这样可以在程序启动时便捷地跳转了,但在多个工程师协同合作时有一个潜在的问题
在项目早期开发阶段,还不需要接入后台网络数据,主要工作的界面的开发。 随着业务页面的深入,要查看二级、三级页面的效果就需要编译后跳转两三次甚至更多,不断地重复这个过程相对来说,就没有可以直接启动就查看那个页面来得那么高效。
1 解决方案
1.1 简单粗暴的方式
常见的做法是在application:didFinishLaunchWithOptions:时直接push到想要到达的页面,如下:
// 获取到可以展示的容器控制器 UINavigationViewController *naviVC = [self getNavigationVC]; // 创建想要跳转的控制器 TargetViewController *targetVC = [[TargetViewController alloc] init]; // 跳转到目标页面 [naviVC pushViewController:targetVC animated:YES]; 复制代码
这样可以在程序启动时便捷地跳转了,但在多个工程师协同合作时有一个潜在的问题
- 是会污染其他同事的代码
- 而多个同事都写了这样的便捷页面跳转而不小心提交到公共代码库就会出代码冲突
1.2 传送门方案VCPicker
为了方便每个协同开发的工程师跳转任意页面,一个更效率的方式有一个入口可以随时找到某一个ViewController页面的类,跳转过去即可,顺着这个思路需要做两个事情:
- 找到工程里所有的ViewController控制器类
- 设置一个统一的入口
实现的途径:
-
利用
objc-runtime
机制获取项目中所有的类,再筛选出所有UIViewController的子类,以字符串的形式保存类名,以列表的形式展现,当点击某一个类时,通过类初始化一个实例即可实现目标页面的跳转
Class *classes = NULL; int numClasses = objc_getClassList(NULL, 0); 复制代码
-
传送门入口的设计,最初是想通过摇一摇来实现从而不影响原有UI的效果,但是不便于模拟器上的使用,所以借鉴了苹果的辅助手势
Assist touch
悬浮球设计,在程序的keyWindow上悬浮一个可以挪动的小球从而在编译进入程序后可以第一时间点击查看控制器列表选择想要跳转的控制器。
// 创建悬浮效果 [[UIDynamicAnimator alloc] initWithReferenceView:self.superview]; 复制代码
2 优化
在使用的过程中逐步衍生并优化了一些有用的功能
2.1 使用class-prefix
由于通过runtime获取到的类有很多是系统的私有类,甚至不响应NSObject协议的,在操作这些类时则会非常危险,此外一些UI的控制器类(比如图片选择、通讯录获取)是需要权限才能访问和创建实例的,而我们实际的项目中一般都有类前缀 class-prefix
(外包的同学不服....),通过类前缀可以快速地筛选出实际项目中的业务页面
2.2 展示方式
根据具体的业务场景基本上分为带导航和不带导航两种,因此使用presentViewController的方法,一种会创建导航控制器后present,另一种则是直接present;
2.3 获取title
有的小伙伴提出,看到的是茫茫的一片类名而不知道业务title不方便同事之间学习,通过分析大部分都会在viewDidLoad方法设置title,或者navigationItem.title或者tabbarItem.title,因此需要实例化一个控制器对象,尝试调用viewDidLoad方法,实践证明如此是不安全的,一方面是viewDidLoad是控制器的生命周期方法原则上是父类调用的,再者很多同学还在viewDidLoad进行了KVO和通知的监听的监听,手动调用viewDidLoad会导致重复监听的问题,而调用[controller view]方法则可以完美地解决这个问题,调用[controller view]方法会在内部依次触发[controller loadView]和[controller viewDidLoad]方法,之后就能获取到想要的title信息;此外,在实例化对象调用view属性触发viewDidLoad时可能因为初始化参数不足的问题抛出异常,因此需要在此处代码块进行@try-catch保护,并保存异常信息提醒当前页面存在潜在异常。
// 创建实例,获取title UIViewController *controller = nil; NSMutableDictionary *dic = [NSMutableDictionary dictionary]; @try { if (_needTitle) { controller = [[NSClassFromString(className) alloc] init]; // nil [controller view]; // to active viewDidLoad so we can get conroller.title } } @catch (NSException *exception) { NSLog(@"[VCPicker <%@> exception: %@]", className, exception); dic[kErrorKey] = exception.description; } @finally { dic[kNameKey] = className; dic[kTitleKey] = controller.title ?: (controller.navigationItem.title ?: (controller.tabBarItem.title ?: className)); [self refreshHistoryForControllerInfo:dic]; [array addObject:dic]; } 复制代码
2.4 增加历史记录和搜索功能
从众多的类列表中,经过 排序 可以方便查找,更方便的方法是提供搜索功能,下次再进入时如果保存了历史记录就更好了,所以这些都要有,所以都有了
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- iOS之导航返回上上个控制器或指定返回某个控制器
- iOS小技巧·把子视图控制器的视图添加到父视图控制器
- javascript – AngularJS控制器错误 – :$http.get不是控制器部分的函数
- AC敏捷控制器及准入控制技术对比
- angularjs – 使用ui-router时,控制器是否可以从父控制器继承范围
- SpringMVC: 前端控制器
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。