您的位置:首页 > 移动开发

利用runTime实现UIWebView 与 JS 随意交互,JS跳转原生页面,亦可实现推送界面万能动态跳转

2017-05-27 17:44 966 查看
相信大家是不是遇到过推送跳转到相关页面进行操作,JS交互时也需要跳转相关的页面,然后这个的页面都是不确定,每次跳转页面也不固定这时我们该怎么做呢?原文链接

简单思路:

1、后台提供json,信息包括:要生成的控制器名称、跳转到该控制器所需的参数值。

2、利用objective-c强大的runtime动态特性,通过NSClassFromString生成控制器对象。

3、利用objective-c强大的runtime动态特性,通过setValue设置控制器对象所需的参数值。

4、获取window的rootViewcontroller,然后实现界面跳转

实现:

首先我们先对NSObject实现一个Category类代码如下:

.h文件

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

@interface NSObject (Skip)

//通过字典生成对象, 根据字典的className决定生成
+(id)objectWithDict:(NSDictionary*)dict;

//设置对象属性值
-(void)setPropertiesWithDict:(NSDictionary*)dict;

//获取对象属性名
- (NSMutableArray*)getProperties;
- (NSMutableArray*)getPropertiesWithClass:(Class)cls;
@end


.m文件

#import "NSObject+Skip.h"

@implementation NSObject (Skip)

/**
*  根据字典生成对象,目前只支持基本类型
*  根据字典的className决定生成
*  @param dict 字典
*
*  @return id
*/
+(id)objectWithDict:(NSDictionary*)dict
{
if (!dict || ![dict objectForKey:@"className"]) {
return nil;
}
Class class = NSClassFromString([dict objectForKey:@"className"]);
id object = [[class alloc]init];
[self setPropertiesWithDict:dict object:object];
return object;
}

/**
*  根据字段设置对象的属性,支持基础属性
*
*  @param dict   字典
*  @param object 要设置的对象
*/
-(void)setPropertiesWithDict:(NSDictionary*)dict object:(id)object
{
Class class;
if ([dict objectForKey:@"className"]) {
class = NSClassFromString([dict objectForKey:@"className"]);
}
else{
class = self.class;
}

NSArray *properties = [self getPropertiesWithClass:class];

for (NSString* key in properties) {
if (dict[key]) {
[object setValue:dict[key] forKey:key];
}
}
}

-(void)setPropertiesWithDict:(NSDictionary*)dict
{
[self setPropertiesWithDict:dict object:self];
}

/**
*  获取某个类的所有字段名
*
*  @param cls 要获取的类class
*
*  @return 返回一个数组
*/
- (NSMutableArray*)getPropertiesWithClass:(Class)cls
{
// 获取当前类的所有属性
unsigned int count;// 记录属性个数
objc_property_t *properties = class_copyPropertyList(cls, &count);
// 遍历
NSMutableArray *mArray = [NSMutableArray array];
for (int i = 0; i < count; i++) {
// objc_property_t 属性类型
objc_property_t property = properties[i];
// 获取属性的名称 C语言字符串
const char *cName = property_getName(property);
// 转换为Objective C 字符串
NSString *name = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
[mArray addObject:name];
}
return mArray.copy;
}

- (NSMutableArray*)getProperties
{
return [self getPropertiesWithClass:self.class];
}

@end


接下来我们写一个跳转控制类SkipManager代码如下:

.h文件

@interface SkipManager : NSObject

//根据json数据 创建我们想要跳转的Controller并对参数进行赋值
+(UIViewController*)createViewControllerWithDict:(NSDictionary*)dict;

//实现跳转
+(UIViewController*)createViewControllerWithDictAndPush:(NSDictionary*)dict;

@end


.m文件

#import "SkipManager.h"
#import "NSObject+Skip.h"

@implementation SkipManager
/**
*  根据字典生成viewcontroller
*
*  @param dict 字典
*
*  @return UIViewController
*/
+(UIViewController*)createViewControllerWithDict:(NSDictionary*)dict{
//storyboard布局,记得在传进来的dict 加上'storyboard': 'Main'
if ([dict objectForKey:@"storyboard"]) {

UIStoryboard* storyboard = [UIStoryboard storyboardWithName:[dict objectForKey:@"storyboard"] bundle:nil];

//记得在storyboard的Storyboard ID改成对应的className
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:dict[@"className"]];

[vc setPropertiesWi
4000
thDict:dict];

return vc;
}else{//纯代码布局和Xib布局

UIViewController *vc = [NSObject objectWithDict:dict];
return vc;
}
}

/**
*  根据字典生成viewcontroller 并自行跳转到vc。
*  所在vc为navigation中则pop到根页并push。
*  所在vc为基本viewcontroller则直接present
*
*  @param dict 字典
*/
+(UIViewController*)createViewControllerWithDictAndPush:(NSDictionary*)dict{

//获取跳转目标Controller
UIViewController *vc = [self createViewControllerWithDict:dict];
if (!vc) {
return nil;
}
//获取根控制器
UIViewController *rootVC = [UIApplication sharedApplication].keyWindow.rootViewController;
//root为tabbar
if ([rootVC isKindOfClass:[UITabBarController class]]) {

UITabBarController *tabVC = (UITabBarController *)rootVC;
UIViewController *tabRootVC = tabVC.viewControllers[tabVC.selectedIndex];
//tabbar的root为navigation 使用navigation跳转 否则 使用present
if ([tabRootVC isKindOfClass:[UINavigationController class]]) {

[(UINavigationController *)tabRootVC pushViewController:vc animated:YES];
}else{
[tabRootVC presentViewController:vc animated:YES completion:nil];
}
}else if([rootVC isKindOfClass:[UINavigationController class]]){
//root为navigation 直接push
[(UINavigationController*)rootVC pushViewController:vc animated:YES];
}else{
//root为uiviewcontroller 直接present
[(UIViewController *)rootVC presentViewController:vc animated:YES completion:nil];
}
return rootVC;
}
@end


到这边就准备完成,只需要后台json数据就可以实现跳转。这里的UIViewController、UINavigationController、UITabBarController都可以换成项目中对应的基类Controller.

使用代码示例:

NSDictionary * dic = @{@"className":@"MessageWebVC",@"strName":@"ssssds",@"index":@"222",@"array":@[@{@"strName":@"¥"},@{@"index":@"666"}],@"dic":@{@"index":@"666"}};
[SkipManager createViewControllerWithDictAndPush:dic];


json格式:

{
className:"MessageWebVC"  //目标类名
storybroad:"Main" //如果是storybroad布局的一定要带参数
strName:"ssss" //对应的参数,这边需要注意参数的类型要对应好
.....
}


完,如果喜欢请关注下,O(∩_∩)O谢谢啦
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息