Use a custom URL to implement jump-B between Controllers

Source: Internet
Author: User
Tags allkeys

An app often has a lot of interfaces, and the interface between the jump is the corresponding controller jump, controller jumps generally have two cases push or modal,push and modal the default effect is provided by the system

Article with picture

1. Overview

The push and modal methods provided by the system sometimes do not meet the actual requirements. For example, we need to jump to the specified controller based on the field returned by the server. That's obviously not the best solution.

In fact, we can do this:

NSString *urlStr = @"dariel://twoitem?name=dariel&userid=213213";       // push     [DCURLRouter pushURLString:urlStr animated:YES];       // modal     [DCURLRouter presentURLString:urlStr animated:YES completion:nil];

Right, is through the custom url+ stitching parameters, to achieve the jump. Of course, the Dcurlrouter:https://github.com/darielchen/dcurlrouter function is much more than that.

Basic use of 2.DCURLRouter

Ps. Dcurlrouter is the OC version, the following can be seen in the swift version of the situation.

Your star is the best support for me.: Smiley:

1. Simple integration

Just drag the Dcurlrouter folder to the project, and the follow-up will support Cocoapods.

2. Simple configuration

    1. Each custom URL will have a corresponding controller, how XOCDE know? We need a plist file. Open dcurlrouter.plist File

      The internal structure is probably long. In addition to the custom URLs are HTTP and HTTPS, this is when the URL is a web link, Dcurlrouter will automatically jump to the custom WebView controller, and pass the URL as a parameter to the WebView controller. Isn't it convenient. The following Dariel dictionary is used to store the custom URL and the corresponding controller name. Dariel is the custom protocol header. You can then put the custom URL and the corresponding controller here.

    2. Loading dcurlrouter.plist file data

- (BOOL)application:(UIApplication *)application  didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {         [DCURLRouter loadConfigDictFromPlist:@"DCURLRouter.plist"];         return YES;}

3. Use of push and modal

All push and modal methods can be called by Dcurlrouter this class method. This way, you don't need to get a navigation controller or controller to jump when you push and modal. In other words, Subsequent push and modal controller jumps are not necessarily performed in the controller.

  1. Push controller

     //Do not require stitching parameters to jump directly [Dcurlrouter pushurlstring:@ "Dariel://twoitem" animated:yes];// Directly stitching the parameters at the end of the custom URL nsstring *urlstr = @ "dariel://twoitem?name=dariel&userid=213213"; [Dcurlrouter pushurlstring:urlstr Animated:yes]; Parameters can be placed in a dictionary nsdictionary *dict = @{@ "UserName": @ "Hello" @ "userid": @ "32342"}; [Dcurlrouter pushurlstring:@ "Dariel://twoitem" Query:dict Animated:yes]; If the current controller and the controller you want to push are the same, you can set replace to Yes for replacement. [Dcurlrouter pushurlstring:@ "Dariel://oneitem" Query:dict animated:yes Replace:yes]; Rewrite the system's push method, jump directly through the controller twoviewcontroller *two = [[Twoviewcontroller alloc] init]; [Dcurlrouter pushviewcontroller:two Animated:yes];  

     

  2. Modal controller

    The usage is similar to push, but here is a way to add a navigation controller to the modal controller.

    // 不需要拼接参数直接跳转 [DCURLRouter presentURLString:@"dariel://threeitem" animated:YES completion:nil]; // 直接把参数拼接在自定义url末尾 NSString *urlStr = @"dariel://threeitem?name=dariel&userid=213213"; [DCURLRouter presentURLString:urlStr animated:YES completion:nil]; // 可以将参数放入一个字典 NSDictionary *dict = @{@"userName":@"Hello", @"userid":@"32342"}; [DCURLRouter presentURLString:@"dariel://threeitem" query:dict animated:YES completion:nil]; // 给modal出来的控制器添加一个导航控制器 [DCURLRouter presentURLString:@"dariel://threeitem" animated:YES withNavigationClass:[UINavigationController class] completion:nil]; // 重写了系统的push方法 ThreeViewController *three = [[ThreeViewController alloc] init]; [DCURLRouter presentViewController:three animated:YES completion:nil];

4. Back pop and dismiss

In actual development, several times the interface of the jump formed a business process, the entire business process after the end will usually require the return to the beginning of the interface, which will let the controller back several times, but Apple does not provide a method. Dcurlrouter gives a concrete implementation of the scheme.

Pop

/** pop掉一层控制器 */     + (void)popViewControllerAnimated:(BOOL)animated;     /** pop掉两层控制器 */     + (void)popTwiceViewControllerAnimated:(BOOL)animated;     /** pop掉times层控制器 */     + (void)popViewControllerWithTimes:(NSUInteger)times animated:(BOOL)animated;     /** pop到根层控制器 */     + (void)popToRootViewControllerAnimated:(BOOL)animated;

Dismiss

/** dismiss掉1层控制器 */     + (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^ __nullable)(void))completion;     /** dismiss掉2层控制器 */     + (void)dismissTwiceViewControllerAnimated: (BOOL)flag completion: (void (^ __nullable)(void))completion;     /** dismiss掉times层控制器 */     + (void)dismissViewControllerWithTimes:(NSUInteger)times animated: (BOOL)flag completion: (void (^ __nullable)(void))completion;     /** dismiss到根层控制器 */     + (void)dismissToRootViewControllerAnimated: (BOOL)flag completion: (void (^ __nullable)(void))completion;

5. Receipt of parameters, and other methods

In 3 if the parameter is spliced after the custom URL, or if the parameter is passed in a dictionary, then how is the destination controller receiving it? In fact, the reception of the parameters is very simple. Just import this category #import "Uiviewcontroller+dcurlrouter.h" on the line, Then you can get these three parameters.

NSLog(@"接收的参数%@", self.params);     NSLog(@"拿到URL:%@", self.originUrl);     NSLog(@"URL路径:%@", self.path);

But sometimes we need to pass the value to the controller that sends the push or the modal side, that is, the reverse pass, is also very simple, can use the proxy or block. There are ways to get the current controller, as well as the navigation controller

// 拿到当前控制器     UIViewController *currentController = [DCURLRouter sharedDCURLRouter].currentViewController;     // 拿到当前控制器的导航控制器     UINavigationController *currentNavgationController = [DCURLRouter sharedDCURLRouter].currentNavigationViewController;

So how to use it is finished, do not know how it feels?

The implementation principle of 3.DCURLRouter custom URL jumps.

1. File structure

First look at a few files for what is the use of each?

    • Dcurlrouter is a singleton, the main class, and all external interfaces are provided by it. We use it to implement custom URL jumps by invoking a class method.

    • Dcurlnavgation is also a singleton, mainly used to rewrite and customize the system's Jump method.

    • Uiviewcontroller+dcurlrouter is the classification of Uiviewcontroller, which is used to receive the parameters of the controller and to create the controller.

    • Dcsingleton a macro for a single case, you can import the. h file into the Dcsingletonh (class name) in the. m file in the class where you want to create the singleton, so that it is easy to create a singleton. See the code in detail.

    • The dcurlrouter.plist is used to store the controller name corresponding to the custom URL.

2. Push principle for a custom URL string

  1. Before jumping we need to set a corresponding controller for the custom URL. Then the push operation in the corresponding controller can be push to the corresponding controller.

    [DCURLRouter pushURLString:@"dariel://threeitem" animated:YES];

  2. After executing the code above, after some simple processing, the end will come here. #import in this method of "Uiviewcontroller+dcurlrouter.h"

    + (Uiviewcontroller *) Initfromurl: (nsurl *) URL withquery: (nsdictionary *) query Fromconfig: (nsdictionary *) configDict {     uiviewcontroller *VC = nil;     nsstring *home;    if (Url.path = = nil) {//Process URL, remove parameters that may be spliced              home = [NSString St  ringwithformat:@ "%@://%@", Url.scheme, Url.host];    }else{             home = [NSString stringwithformat:@ "%@://%@%@", Url.sc  Heme, Url.host,url.path];    }    if ([Configdict.allkeys containsObject:url.scheme]) {//All keys in the dictionary contain incoming protocol headers     & nbsp        id config = [configdict objectForKey:url.scheme]; Fetch values according to the protocol header              class Class = nil;              if ([Config iskindofclass:[nsstring class]) {//When the protocol header is HTTP HTTPS,   & nbsp                  class =  nsclassfromstring (config);               }else if ([Config Iskindofclass:[nsdictionary class]]) {//Custom URL condition                      nsdictionary *dict = (nsdictionary *) config;                     if ([Dict.allkeys Containsobject:home]) {  &NBSP ;                     class =  nsclassfromstring ([dict objectforkey:h OME]); According to key to get the corresponding controller name                  }          } &nb Sp        IF (class!=nil) {                 VC = [[Class all] Oc]init];                  if ([VC respondstoselector: @selector (open:withquery:)]) {& nbsp                        [VC Open:url withQuery:query];                }        //processing network Address         if ([Url.scheme isequaltostring:@ "http"] | | [Url.scheme isequaltostring:@ "https"]) {                class =  nsclassfromstring ([configdict ObjectForKey:url.sch EME]);             Vc.params = @{@ "urlstr": [url absolutestring]};        }  }   return VC;}

    In this method, the custom URL is created as the corresponding controller. The specific what the writing is very clear, not detailed said Ah!

  3. Receiving of the pass parameter

    Notice the above [VC Open:url withquery:query]; ? The assignment is done in the following method, but we all have a common sense, how to save the attribute in the classification?

    - (void)open:(NSURL *)url withQuery:(NSDictionary *)query{     self.path = [url path];     self.originUrl = url;     if (query) {   // 如果自定义url后面有拼接参数,而且又通过query传入了参数,那么优先query传入了参数              self.params = query;     }else {              self.params = [self paramsURL:url];     }}

    The answer is that with runtime, runtime can do this for us.

    - (void)setOriginUrl:(NSURL *)originUrl {       // 为分类设置属性值     objc_setAssociatedObject(self, &URLoriginUrl,                           originUrl,                           OBJC_ASSOCIATION_RETAIN_NONATOMIC);}- (NSURL *)originUrl {     // 获取分类的属性值     return objc_getAssociatedObject(self, &URLoriginUrl);}

  4. In the Dcurlrouter method we can get the VC returned in 2, and then we need to call the push method in the Dcurlnavgation

    + (void)pushURLString:(NSString *)urlString animated:(BOOL)animated {     UIViewController *viewController = [UIViewController initFromString:urlString fromConfig:[DCURLRouter sharedDCURLRouter].configDict];     [DCURLNavgation pushViewController:viewController animated:animated replace:NO];}

  5. How to handle push in dcurlnavgation

    + (void) Pushviewcontroller: (Uiviewcontroller *) Viewcontroller animated: (BOOL) animated replace: (BOOL) Replace {       if (!viewcontroller) {             nsassert (0, @ "Please add a match to the URL  The controller to the plist file, or the protocol header may have been incorrectly written! ");    }else {             if ([Viewcontroller iskindofclass:[ Uinavigationcontroller class]) {                 [dcurlnavgation Setrootvie Wcontroller:viewcontroller];              }//If the navigation controller is set directly to the root controller              els e {                     uinavigationcontroller *navigationcontroll ER = [dcurlnavgation shareddcurlnavgation].currentnavigationviewcontroller;              if (Navigationcontroller) {//Navigation controller presence                                  //in case it should replace, look for the last Uiviewcontroller on the U Inavigationcontroller, if it ' s of the same class, replace it with a new one.                                if   () Replace && [NavigationController.viewControllers.lastObject Iskindofclass:[viewcontroller class]] {  & nbsp                                  NSA Rray *viewcontrollers = [Navigationcontroller.viewcontrollers subarraywithrange:nsmakerange (0, NAVIGATIONCONTROLLER.VIEWCONTROLLERS.COUNT-1)];                          ,         &NB Sp  [navigationcontroller Setviewcontrollers:[viewcontrollers Arraybyaddingobject:viewcontroller] Animated: Animated];             &NBSp            }//Toggle the current navigation controller to have the original sub-controller removed to re-add             &NBS P             else {                    &NB Sp             [Navigationcontroller Pushviewcontroller:viewcontroller animated:animated];                           }//push                  }else {                    & nbsp     Navigationcontroller = [[Uinavigationcontroller Alloc]initwithrootviewcontroller:viewcontroller];                           [Dcurlnavgation Shareddcurlnavg Ation].applicationdelegate.window.rootviewcontroller = Navigationcontroller;                  }//If the navigation controller does not exist, a new one is created, set to root controller          }  }} 

    Code written in a very detailed, not detailed said Ah!

  6. Probably the same, how to deal with modal in dcurlnavgation

    + (void) Presentviewcontroller: (Uiviewcontroller *) Viewcontroller animated: (BOOL) flag completion: (void (^ __nullable) (void)) Completion {   IF (!viewcontroller) {             nsassert (0, @ "Please add a match to the URL  The controller to the plist file, or the protocol header may have been incorrectly written! ");    }else {             uiviewcontroller *currentviewcontroller = [[Dcurlnavg ation shareddcurlnavgation] Currentviewcontroller];               if (Currentviewcontroller) {//Current controller exists                      [currentviewcontroller Presentviewcontroller:viewcontroller Animated:flag Completion:completion];              } else {//Set Controller as root controller               nbsp      [dcurlnavgation Shareddcurlnavgation].applicationdelegate.window.rootviewcontroller = Viewcontroller;           &NBsp  }  }}

    The code is also very detailed, there is a problem can leave a message below!

4. How to load a custom WebView controller

In the above 3.2.2, do not know whether to notice that the network address processing

// 处理网络地址的情况  if ([url.scheme isEqualToString:@"http"] || [url.scheme isEqualToString:@"https"]) {      class = NSClassFromString([configDict objectForKey:url.scheme]);      VC.params = @{@"urlStr": [url absoluteString]};

If the protocol header is HTTP or HTTPS, we can get the name of the custom WebView controller by [Configdict ObjectForKey:url.scheme] and then we'll create the WebView controller, then we'll pass the URL through the parameter To the WebView controller, and finally load the corresponding webview in the WebView controller.

5. How to implement the one-time pop and dismiss multi-layer controller implementation principle.
  1. Pop controller

    + (void) Popviewcontrollerwithtimes: (Nsuinteger) times animated: (BOOL) animated {         Uiviewcontroller *currentviewcontroller = [[Dcurlnavgation shareddcurlnavgation] currentviewcontroller];     nsuinteger count = CurrentViewController.navigationController.viewControllers.count;    if (Currentviewcontroller) {             IF ( Currentviewcontroller.navigationcontroller) {                      if (Count > times) {                            & nbsp [Currentviewcontroller.navigationcontroller poptoviewcontroller:[ CurrentViewController.navigationController.viewControllers Objectatindex:count-1-times] animated:animated];                      }else {//if times are greater than the number of controllers     &NBSP ;               &NBsp        nsassert (0, @ "OK to pop out so many controllers?");                       }            }  }}

    Popviewcontroller implementation of the idea is relatively simple, because you can get all the controller on the navigation controller, and then through the Objectatindex this method. This will do it.

  2. Dismiss Controller

    + (void)dismissViewControllerWithTimes:(NSUInteger)times animated: (BOOL)flag completion: (void (^ __nullable)(void))completion {     UIViewController *rootVC = [[DCURLNavgation sharedDCURLNavgation] currentViewController];     if (rootVC.presentedViewController) {              while (times > 0) {                      rootVC = rootVC.presentingViewController;                      times -= 1;              }              [rootVC dismissViewControllerAnimated:YES completion:completion];     }else {              NSAssert(0, @"确定能dismiss掉这么多控制器?");     }}

    Dismissviewcontroller This idea of implementation is a bit special, because there is no way to get all the modal out of the controller, can only get the last, so this side is used while loop implementation.

5. Summary

Probably said under the specific use and approximate function of the implementation, there are many specific implementation details, interested in children's shoes can see the source code!

Dcurlrouter Module Source: Https://github.com/DarielChen/DCURLRouter

Use a custom URL to implement jump-B between Controllers

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.