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

1 篇文章 0 订阅
1 篇文章 0 订阅

相信大家是不是遇到过推送跳转到相关页面进行操作,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 setPropertiesWithDict: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谢谢啦

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值