需求背景:
1.在一般的项目中,都会有很页面,这样就会出现好多push、present。要找到一个指定页面的跳转,就得去找具体对应代码。查看跳转的参数、这样重复代码较多、而且比较繁琐。如果能够统一管理跳转逻辑、这样就简单多了、只要在同一个地方打断点、查看传递参数就好了。
2.有一个这样的场景、由一个网页的活动页面、跳转至app特定页面、利用一个url、也会简单方便。
3.推送跳转到指定页面
Schemes
我们知道每个app都有自己独立的沙盒、互相独立。这样阻碍了app之间的通信。苹果给我们的通信是通过URL Schemes。只要每个app定义了自己的Schemes,便能实现app之间跳转。苹果系统原生的app、比如打电话tel://等。还有一些第三方的,比如支付宝alipay://。如果在手机同时装了两个Schemes一摸一样的app,我猜想应该是跳转先安装、或者优先采取苹果自己默认的app。所有设置URL Schemes,还是要注重唯一性、这样就不会重复,最好跟bundle identifier一致。
在safari浏览器输入、也会识别到、如下图所示:(图一是alipay://图二为自定义app)
其实Scheme 就是://前面的英文字符。支付宝为alipay、项目中设置如下图:(info中的URL Types中)
跳转的url就是SKJLRoutes://。
路由跳转、就是约定一个url。也就是根据Scheme进行跳转,设置跳转统一逻辑。下面用一个三方JLRouts简单举例说明。
实现如下图的跳转: 页面一跳转到页面一
首先设置好URL Schemes 、暂时就为SKJLRoutes,然后pod引入三方 pod 'JLRoutes' 在appdelegate注册:写入相关代码。
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
NSLog(@"URL scheme:%@", [url scheme]);
return [[JLRoutes globalRoutes] routeURL:url];
}
复制代码
约定好push、present跳转url
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
ViewController *viewCtr = [[ViewController alloc]init];
UINavigationController *na = [[UINavigationController alloc]initWithRootViewController:viewCtr];
self.window.rootViewController = na;
// Push规则
[[JLRoutes globalRoutes] addRoute:@"/NaPush/:controller" handler:^BOOL(NSDictionary<NSString *,NSString *> * _Nonnull parameters) {
NSLog(@"parameters==%@",parameters);
UIViewController *v = [[NSClassFromString(parameters[@"controller"]) alloc] init];
[self paramToVc:v param:parameters];
[(UINavigationController*)[self getCurrentVC] pushViewController:v animated:YES];
return YES;
}];
// Present规则
[[JLRoutes globalRoutes] addRoute:@"/Present/:controller" handler:^BOOL(NSDictionary<NSString *,NSString *> * _Nonnull parameters) {
NSLog(@"parameters==%@",parameters);
UIViewController *v = [[NSClassFromString(parameters[@"controller"]) alloc] init];
[self paramToVc:v param:parameters];
[[self getCurrentVC] presentViewController:v animated:YES completion:^{}];
return YES;
}];
return YES;
}
复制代码
我们可以看到block中parazmetes为页面传来的参数、controller则为跳转到的控制器。 利用响应者链获取当天控制器、runtime传递参数即可(这部分代码百度而来):
-(void)paramToVc:(UIViewController *) v param:(NSDictionary<NSString *,NSString *> *)parameters
{
//runtime将参数传递至需要跳转的控制器
unsigned int outCount = 0;
objc_property_t * properties = class_copyPropertyList(v.class , &outCount);
for (int i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
NSString *key = [NSString stringWithUTF8String:property_getName(property)];
NSString *param = parameters[key];
if (param != nil) {
[v setValue:param forKey:key];
}
}
}
复制代码
当点击button按钮时,采取url跳转即可:
NSString *customURL = @"SKJLRoute://NaPush/PersonalCenterViewController?userID=20";
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:customURL] options:@{UIApplicationOpenURLOptionsSourceApplicationKey : @YES} completionHandler:nil];
复制代码
PersonalCenterViewController为第二个控制器、userID为参数。
完整url即为SKJLRoute://NaPush/PersonalCenterViewController?userID=20。 这个和常规的网络跳转链接url很像(类似get),这样我们无论跳转那个页面,不需去找特定的跳转action、只有在appdelegate的block中打印参数即可。
parameters=={
JLRoutePattern = "/NaPush/:controller";
JLRouteScheme = JLRoutesGlobalRoutesScheme;
JLRouteURL = "SKJLRoute://NaPush/PersonalCenterViewController?userID=20";
controller = PersonalCenterViewController;
userID = 20;
}
复制代码