推送消息 跳转到指定控制器


一、前言

  • 1、最近整理以前项目的资料,处理推送消息的时候显示只能在主页面,安卓那边就很好处理,可以根据不同的推送消息指定跳转到任意控制器,那么iOS 能不能实现呢?答案是肯定的!

  • 2、需要后台配合,传一个要跳转的控制器的名字以及指定控制器所需参数 原文 地址 ,简单说说这种方式出现的问题吧

  • 问题一

没有封装工具类使用,delegate里面实现并处理逻辑,这显然不应该是delegate去做,造成delegate 冗余

  • 问题二

面向字典开发,可复用性差,处理情况单一(json格式定死),逻辑处理不完善,数据获取麻烦且容易出错(需要写key,字符串容易出错,如果需要多次使用就更麻烦)


二、完善

  • 1、封装工具类,继承NSObject,解耦合,移植性、复用性、拓展性强,对外提供一个方法,专门处理推送消息,自动跳转控制器,交给专业的人去做,更加面向对象

  • 2、面向模型,后台返回json数据,转模型存储数据,存储方便,不容易出错,而且如果后台返回的json格式不一样了,我依然可以创建子类,重写构造方法进行特殊处理,而且面向模型开发,直观


三、API 设计

  • 1、工具类一般弄成单例,需要一个单例创建方法,还需要对外提供一个方法,接收到外界数据后,处理逻辑并跳转到指定控制器

  • 2、数据当然从模型里面那,因此还需要一个模型类,专门存储消息数据,在工具类中创建,统一管理,最关键、最重要的是claseName属性,后台必须返回一个需要跳转的控制器的名字给我,其他不同控制器对应的属性,就交给子类去添加,有属性当然就需要自定义构造方法,字典转模型嘛

FLRemotePushModel 模型

  • 子类继承,对应不同的控制器所需的参数,添加对应的属性到子类中,默认层级都是同一级,子类可重写fl_remotePushModel方法,对应不同的字典转模型
  • 注意一点:子类中所添加的属性,应该都为对象,基本数据类型不行喔,而且后台返回的都是对象,基本数据用NSNumber包装

/**
 *  @author Clarence-lie, 16-09-08 22:09:01
 *
 *  需要跳转的类名,后台返回
 */
@property (nonatomic,copy)NSString *className;
/**
 *  @author Clarence-lie, 16-09-08 22:09:38
 *
 *  字典转模型,可重写,根据不同格式转模型(如果重写,需要调用父类)
 *
 *  @param dict 后台返回的字典(json)
 *
 *  @return 返回一个模型
 */
+ (instancetype)fl_remotePushModel:(NSDictionary *)dict;

FLRemotePushManager 管理工具

/**
 *  @author Clarence-lie, 16-09-08 22:09:59
 *  创建单例对象,方便管理
 */
+ (instancetype)fl_shareInstance;
/**
 *  @author Clarence-lie, 16-09-08 22:09:59
 *
 *  根据模型内容跳转到指定界面
 *
 *  @param remotePushModel FLRemotePushModel子类
 */
- (void)fl_pushWithRemotePushModel:(FLRemotePushModel *)remotePushModel;

四、实现

大概思路:根据json数据创建模型 -> 工具类获取模型数据 -> 根据类名创建控制器实例对象 -> 获取模型对象属性名并存储到数组中 -> 遍历模型属性名数组并判断控制器实例对象是否有对应属性 -> 有对应属性则通过KVC赋值给控制器 -> 获取导航控制器进行跳转
定时器模拟推送消息

  • 关键代码简析
  • 1.获取对象的属性列表: class_copyPropertyList

unsigned int outCount, i;
// 获取对象里的属性列表
objc_property_t * properties = class_copyPropertyList([instance class], &outCount);
  • 2.通过属性名创建对应属性的getter方法:NSSelectorFromString OC的getter方法就是属性的本身
/**
 *  @author Clarence-lie, 16-09-08 22:09:33
 *
 *  通过字符串来创建该字符串的getter方法
 *
 *  @param propertyName 属性名
 *
 *  @return 对应的getter方法
 */
- (SEL)fl_creatGetterWithPropertyName: (NSString *) propertyName{
    //1.返回get方法: oc中的get方法就是属性的本身
    return NSSelectorFromString(propertyName);
}
  • 3.获取属性名对应的属性值:获得方法签名(getter方法)-> 签名中获取调用对象 -> 设置对象的target -> 设置对象的方法 -> 发送消息 -> 接收返回值(就是属性值)
/**
 *  @author Clarence-lie, 16-09-08 22:09:49
 *
 *  获取指定属性名对应的值
 *
 *  @param propertyName 属性名
 *
 *  @return 属性值
 */
- (id)fl_getValueByPropertyName:(NSString *)propertyName{
    //获取get方法
    SEL getSel = [self fl_creatGetterWithPropertyName:propertyName];
    
    if ([self respondsToSelector:getSel]) {
        
        //获得方法的签名
        NSMethodSignature *signature = [self methodSignatureForSelector:getSel];
        
        //从签名获得调用对象
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
        
        //设置target
        [invocation setTarget:self];
        
        //设置selector
        [invocation setSelector:getSel];
        
        //接收返回的值
        NSObject *__unsafe_unretained returnValue = nil;
        
        //发消息
        [invocation invoke];
        
        //接收返回值
        [invocation getReturnValue:&returnValue];
        
        return returnValue;
    }
    else{
        return nil;
    }
}

五、调用

调用起来很简单,只需要创建好对应的推送模型,然后执行 fl_pushWithRemotePushModel 方法就行

- (void)pushSecond
{
    // 跟服务端沟通好跳转对应的界面需要对应的参数以及格式
    NSDictionary *userInfo = @{
                               @"className": @"SecondViewController",
                               @"id": @"12",
                               @"content": @"测试推送内容消息"
                               };
    
    [[FLRemotePushManager fl_shareInstance] fl_pushWithRemotePushModel:[FLSecondVcRemoteModel fl_remotePushModel:userInfo]];
}

- (void)pushThird{
    // 非默认同一级的json格式,子类重写构造方法即可
    NSDictionary *userInfo = @{
                               @"className": @"ThirdViewController",
                               @"msg"      : @{
                                    @"name": @"clarence",
                                     @"age": @12
                                             }
                               };
    
    [[FLRemotePushManager fl_shareInstance] fl_pushWithRemotePushModel:[FLThirdVcRemoteModel fl_remotePushModel:userInfo]];
}

六、总结

  • ** 1、注意:必须跟后台配合,定好规则,哪条推送消息需要跳转到哪个控制器、以及该控制器中请求后台所需的参数都要返回给客户端,归根到底还是利用了OC的运行时特点,可以获取对象以及对象属性、方法**

  • ** 2、如果推送页面都是固定的,可以直接写死,只需要传入不同参数就行,但是如果是不固定的,当然,可以传入不同的type 然后前台判断,跳转不同的控制器,此时相对就没那么直观,但确安全很多,因为控制器名是字符串,写错了就没办法,当然,框架中处理了,如果没找到指定的控制器 ,就会创建新的,看需求**

  • ** 3、实现比较简单,关键还是思路,详细的Demo都在 GitHub 上面,欢迎大家关注我,喜欢给个like 和 star **

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,076评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,658评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,732评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,493评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,591评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,598评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,601评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,348评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,797评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,114评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,278评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,953评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,585评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,202评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,180评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,139评论 2 352

推荐阅读更多精彩内容

  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,946评论 6 13
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,647评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,014评论 25 707
  • 我不知道为什么 只要你发过来微信我都会觉得开心 一年了, 每次都是心中窃喜。 是不是我爱你太深? 是不是我对你还是...
    静默等你阅读 251评论 0 0
  • p5
    AJI米阅读 56评论 0 0