美文网首页
iOS-runtime实践-消息推送跳转到任意页面并赋值

iOS-runtime实践-消息推送跳转到任意页面并赋值

作者: c6e16b2e3a16 | 来源:发表于2017-04-17 22:57 被阅读106次

    runtime的概念和作用不在这里多阐述,网上的文章很多.runtime的功能虽然很强大,但是在实际项目中写业务代码时很少用到.字典转Model已经有很好的轮子了,我们不用再自己去写(学习除外);非特殊情况,替换系统方法也几乎不会用到.本文介绍一种常见的runtime应用场景:消息推送.

    应用收到消息推送时,会根据推动内容跳转到相应页面(控制器).推送消息的内容是以key:value的形式发送的,因此需要根据key:value来动态生成页面并跳转.

    问题转换:根据字典来动态创建控制器并跳转.

    1.约定推送消息(字典)格式

    下图是友盟推送后台,消息推送时设置key:value键值对

    image.png

    因为要跳转到指定页面(控制器),则必须有一个键值对传递目标控制器的名称.其他的键值对可以是该页面所需要的属性值.

    假设我的应用中有一个个人页面,需要根据推送内容显示推送的用户信息:

    #import "PersonalViewController.h"
    
    @interface PersonaViewController ()
    
    @property (copy, nonatomic) NSString *name;
    @property (assign, nonatomic) NSInteger age;
    @property (copy, nonatomic) NSString *tel;
    
    @end
    
    @implementation PersonalViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
        NSLog(@"%@, %ld, %@", _name, _age, _tel);
    }
    
    @end
    

    那么推送消息内容可以这样设置:


    E4791666-0082-4A37-ACB5-DFD2054BEE26.png

    className是类名称
    其他参数是该类所需要的属性值

    2.APP接收通知并跳转

    创建UINavigationController消息通知处理分类方便管理.

    #import <UIKit/UIKit.h>
    
    @interface UINavigationController (RemoteNotify)
    
    - (void)pushWithUserInfo:(NSDictionary *)userInfo;
    
    @end
    
    #import "UINavigationController+RemoteNotify.h"
    #import <objc/runtime.h>
    
    @implementation UINavigationController (RemoteNotify)
    
    - (void)pushWithUserInfo:(NSDictionary *)userInfo {
        if ([userInfo.allKeys containsObject:@"className"]) {
            NSString *className = [userInfo objectForKey:@"className"];
            Class class = NSClassFromString(className);
            id instance = [[class alloc] init];
            if (instance) {
                [userInfo enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
                    if (![key isEqualToString:@"className"]) {
                        if ([self containsProperty:instance key:key]) {
                            [instance setValue:obj forKey:key];
                        } else {
                            NSLog(@"不包含(%@:%@)", key, obj);
                        }
                    }
                }];
                [self pushViewController:instance animated:YES];
            }
        }
    }
    
    - (BOOL)containsProperty:(id)instance key:(NSString *)key {
        unsigned int count;
        objc_property_t *properties = class_copyPropertyList([instance class], &count);
        for (int i = 0; i < count; i++) {
            objc_property_t property = properties[i];
            NSString *name = [NSString stringWithCString: property_getName(property) encoding:NSUTF8StringEncoding];
            if ([key isEqualToString:name]) {
                return YES;
            }
        }
        free(properties);
        return NO;
    }
    
    @end
    

    在AppDelegate的消息接收方法中调用

    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
        //获取当前控制器
        UITabBarController *rootCtrl = (UITabBarController *)self.window.rootViewController;
        UINavigationController *currentCtrl = (UINavigationController *)rootCtrl.selectedViewController; 
        //从当前控制器push到指定控制器
        [currentCtrl pushWithUserInfo:userInfo];
    }
    

    相关文章

      网友评论

          本文标题:iOS-runtime实践-消息推送跳转到任意页面并赋值

          本文链接:https://www.haomeiwen.com/subject/bsstzttx.html