0 background

In the early development stage of the project, there is no need to access background network data, and the main work interface development. As you get deeper into a business page, you need to jump two or three times or more after compiling to see the effect of a second or third level page. Repeating this process over and over is not as efficient as viewing the page when you can just launch it.

1 Solution

1.1 The simple and crude way

Is common practice in the application: didFinishLaunchWithOptions: directly push to you want to get to the page, as follows:

/ / get to can show container controller UINavigationViewController * naviVC = [self getNavigationVC]; TargetViewController *targetVC = [[TargetViewController alloc] init]; / / jump to the target page [naviVC pushViewController: targetVC animated: YES];Copy the code

This makes it easy to jump around at startup, but there is a potential problem with multiple engineers working together

  • Is to contaminate other colleagues’ code
  • Multiple colleagues have written such a quick page jump and accidentally commit to a common code base, resulting in code conflicts

1.2 Portal scheme VCPicker

In order to make it easier for each developer to jump to any page, a more efficient way is to have a portal where you can find the class of a particular ViewController page at any time and jump to it. Along the way, you need to do two things:

  • Find all the ViewController classes in your project
  • Set up a unified entrance

The way to achieve:

  • usingobjc-runtimeThe mechanism obtains all the classes in the project, and then selects all the subclasses of UIViewController, saves the class name in the form of string, and presents it in the form of list. When clicking on a class, an instance initialized by the class can realize the jump to the target page
    Class *classes = NULL;
    int numClasses = objc_getClassList(NULL, 0);
Copy the code
  • The portal portal was originally designed to be shaken so as not to affect the UI, but it was not easy to use on the simulator, so it borrowed from Apple’s auxiliary gesturesAssist touchSuspension ball design, suspend a movable ball in the keyWindow of the program, so that after compiling and entering the program, you can click the list of controllers to select the controller you want to jump to.
/ / create the suspension effect [[UIDynamicAnimator alloc] initWithReferenceView: self. The superview];Copy the code

Two optimization

In the process of use gradually derived and optimized some useful functions

2.1 use the class – the prefix

Because many of the classes acquired through runtime are private to the system and don’t even respond to NSObject, it can be dangerous to manipulate these classes, and some UI controller classes (such as image selection and address book retrieval) require permissions to access and create instances. However, our actual projects generally have class prefix (….). , the class prefix can be used to quickly screen out the business pages in the actual project

2.2 Display Mode

According to the specific business scenario is basically divided into two types with and without navigation, so use presentViewController method, one will create navigation controller present, the other is directly present;

2.3 to obtain the title

Navigationitem. title/tabbaritem. title/navigationItem.title/navigationItem.title/navigationItem.title So you need to instantiate a controller object and try to call viewDidLoad, and it turns out that it’s not safe to do that, because viewDidLoad is a controller lifecycle method and it’s called by its parent class in principle, and a lot of you have done KVO and notification listening on viewDidLoad, Manually calling viewDidLoad causes repetitive listening problems, which are perfectly fixed by calling the [Controller View] method, Calling the [Controller View] method internally fires the [Controller loadView] and [Controller viewDidLoad] methods, after which the desired title information is retrieved; In addition, an exception may be thrown when the instantiated object calls the View property to trigger viewDidLoad due to insufficient initialization parameters, so you need @try-catch protection in this code block and save exception information to alert the current page to potential exceptions.

// create instance, get 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]; }Copy the code

2.4 Added the History and search functions

It’s easy to sort through a list of classes, and it’s even easier to provide a search function, and it would be nice if you saved your history the next time you enter, so you have all of that, so you have all of that

Thanks to Zoro and Ace students for their excellent advice during development

The application is carried out in the actual development project, and the internal implementation uses DEBUG macro to precompile judgment to ensure that there will be no problems when it goes online. The application can be audited and launched in App Store without removing VCPicker.

3 Source code and Demo

demo