iOS 路由跳转

项目中我们会有很多的页面,我们就需要不断的push或者present

如果我们能够实现路由跳转(像网页一样通过一个URL地址去访问)就会方便很多

那么我们今天就来讨论下页面使用路由跳转

一、首先我们要清楚一些基本概念

1、scheme

每个app都有自己独立的沙盒、互相独立。这样阻碍了app之间的通信。

苹果给我们的通信是通过URL Schemes。只要每个app定义了自己的Schemes,便能实现app之间跳转。

苹果系统原生的app、比如打电话tel://等。还有一些第三方的,比如支付宝alipay://

其实scheme 就是://前面的英文字符

路由跳转就是约定一个url。也就是根据scheme进行跳转

2、NSURL

复制代码
/* Any URL is composed of these two basic pieces.  The full URL would be the concatenation of [myURL scheme], ':', [myURL resourceSpecifier]
 */
@property (nullable, readonly, copy) NSString *scheme;
@property (nullable, readonly, copy) NSString *resourceSpecifier;

/* If the URL conforms to rfc 1808 (the most common form of URL), the following accessors will return the various components; otherwise they return nil.  The litmus test for conformance is as recommended in RFC 1808 - whether the first two characters of resourceSpecifier is @"//".  In all cases, they return the component's value after resolving the receiver against its base URL.
 */
@property (nullable, readonly, copy) NSString *host;
@property (nullable, readonly, copy) NSNumber *port;
@property (nullable, readonly, copy) NSString *user;
@property (nullable, readonly, copy) NSString *password;
@property (nullable, readonly, copy) NSString *path;
@property (nullable, readonly, copy) NSString *fragment;
@property (nullable, readonly, copy) NSString *parameterString API_DEPRECATED("The parameterString method is deprecated. Post deprecation for applications linked with or after the macOS 10.15, and for all iOS, watchOS, and tvOS applications, parameterString will always return nil, and the path method will return the complete path including the semicolon separator and params component if the URL string contains them.", macosx(10.2,10.15), ios(2.0,13.0), watchos(2.0,6.0), tvos(9.0,13.0));
@property (nullable, readonly, copy) NSString *query;
复制代码

例如:

NSURL *url = [NSURL URLWithString:@"http://www.baidu.com/test/mypath?test=baiduhome&number=123"];

scheme http

host www.baidu.com

path /test/mypath

query test=baiduhome&number=123

二、实现原理

1、创建一个单例对象拥有一个可变字典,用来保存键值对

2、以query之前为key 类名为value 在每个页面的load方法中完成注册

3、在每个页面实现具体跳转逻辑

例如:

NSURL *url = [NSURL URLWithString:@"project://test/mypath?test=baiduhome&number=123"];

key project://test/mypath

value TestViewController

SchemeProtocol

复制代码
typedef void(^SchemeCompletion)(id objc);

@protocol SchemeProtocol <NSObject>
// 跳转方法
+ (void)SchemeData:(NSDictionary *)data
                    url:(NSString *)url
             completion:(SchemeCompletion)handler;

@end
复制代码

 SchemeTool

复制代码
@interface SchemeTool()

@property (nonatomic,strong) NSMutableDictionary *modules;
@end

@implementation SchemeTool

#pragma mark - Instancet

+ (instancetype)shared {
    
    static SchemeTool * schemeTool = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        schemeTool = [[SchemeTool alloc] init];
    });
    return schemeTool;
}

- (instancetype)init{
    self = [super init];
    if (self) {
       _modules = [[NSMutableDictionary alloc] init];
    }
    return self;
}

// 注册 url与Class绑定

+ (void)registerModule:(Class)moduleClass pathName:(NSString *)pathName{

    [iComeSchemeTool shared].modules[pathName] = moduleClass;

}

// 跳转 通过url实现跳转

+ (void)receiveSchemeURL:(NSURL *)schemeURL completion:(SchemeCompletion)handler{

    

    NSString *query = schemeURL.query;

    NSString *key = [[schemeURL.absoluteString componentsSeparatedByString:@"?"] firstObject];

//    通过url找到对应Class

    Class ocClass = [SchemeTool shared].modules[key];

//    判断是否实现跳转方法

    if (ocClass &&

        [ocClass respondsToSelector:@selector(SchemeData:url:completion:)]){

//        解析query

        NSDictionary *dic = [SchemeTool queryDicWithStr:query];

//        调用跳转方法

        [[ocClass class] SchemeData:dic url:schemeURL.absoluteString completion:handler];

        

    }else {

//        未实现跳转方法

    }

}

// 解析query

+ (NSDictionary *)queryDicWithStr:(NSString *)queryStr{

    NSMutableDictionary *dict = [NSMutableDictionary new];

    NSArray *paramArray = [queryStr componentsSeparatedByString:@"&"];

    for (NSString *param in paramArray) {

        if (param && param.length) {

            NSRange range = [param rangeOfString:@"="];

            if (range.location != NSNotFound) {

                NSString *keyStr = [param substringToIndex:range.location];

                NSString *valueStr = [param substringFromIndex:range.location+range.length];

                dict[keyStr] = valueStr;

            }else{

                dict[param] = param;

            }

        }

    }

    return dict;

}

复制代码

TestViewController

复制代码
@implementation TestViewController

+ (void)load {

// 注册 url与Class 绑定

   [SchemeTool registerModule:[self class] pathName:@"project://test/mypath"];

}

// 跳转方法
+ (void) SchemeData:(NSDictionary *)data url:(NSString *)url completion:(SchemeCompletion)handler { TestViewController *vc = [[TestViewController alloc] init]; vc.test = data[@"test"]; [[WOWSUtils getCurrentVC] pushViewController:vc]; }
复制代码

 

posted @   小菜看代码  阅读(548)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
历史上的今天:
2021-07-21 iOS sizeForItemAtIndexPath方法在iOS14下变化
点击右上角即可分享
微信分享提示