[iOS][OC] 开发利器:控制器传送门VCPicker(附d

2018-11-07  本文已影响1人  BudSwift

0 背景

在项目早期开发阶段,还不需要接入后台网络数据,主要工作的界面的开发。
随着业务页面的深入,要查看二级、三级页面的效果就需要编译后跳转两三次甚至更多,不断地重复这个过程相对来说,就没有可以直接启动就查看那个页面来得那么高效。

1 解决方案

1.1 简单粗暴的方式

常见的做法是在application:didFinishLaunchWithOptions:时直接push到想要到达的页面,如下:

 //  获取到可以展示的容器控制器
UINavigationViewController *naviVC = [self getNavigationVC];
// 创建想要跳转的控制器
TargetViewController *targetVC = [[TargetViewController alloc] init]; 
// 跳转到目标页面
[naviVC pushViewController:targetVC animated:YES]; 

这样可以在程序启动时便捷地跳转了,但在多个工程师协同合作时有一个潜在的问题

1.2 传送门方案VCPicker

为了方便每个协同开发的工程师跳转任意页面,一个更效率的方式有一个入口可以随时找到某一个ViewController页面的类,跳转过去即可,顺着这个思路需要做两个事情:

实现的途径:

    Class *classes = NULL;
    int numClasses = objc_getClassList(NULL, 0);
// 创建悬浮效果
[[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 增加历史记录和搜索功能

从众多的类列表中,经过排序可以方便查找,更方便的方法是提供搜索功能,下次再进入时如果保存了历史记录就更好了,所以这些都要有,所以都有了

感谢开发过程中Zoro和Ace同学的极好的建议

在实际开发项目中进行应用,内部实现使用DEBUG宏进行预编译的判断,确保上线时不会出问题,使用VCPicker不用移除也可以正常审核上线App store。

3 源代码和demo

demo

加我微信沟通。


上一篇下一篇

猜你喜欢

热点阅读