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

1.前言

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

  • 逛gitHub,真有人实现了,能跳转,不过需要后台配合,传一个要跳转的控制器的名字以及指定控制器所需参数 原文 地址 ,原文代码就不拷贝过来了,简单说说出现的问题吧

    • 问题一

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

    • 问题二

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


2.完善

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

  • 面向模型,后台返回json数据,转模型存储数据,存储方便,不容易出错,而且如果后台返回的json格式不一样了,我依然可以创建子类,重写构造方法进行特殊处理,而且面向模型开发,不也更面向对象吗?哈哈,反正我喜欢模型


3.API 设计

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

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

/*
 *  @author Clarence-lie 孔凡列
 *
 *  QQ:279761135
 *
 *  gitHub:https://github.com/gitkong
 *  cocoaChina:http://code.cocoachina.com/user/index/upload/
 *  简书 : http://www.jianshu.com/users/fe5700cfb223/latest_articles
 *  喜欢给个like & star呗~
 */

#import <Foundation/Foundation.h>
/**
 *  @author Clarence-lie, 16-09-08 21:09:07
 *
 *  子类继承,对应不同的控制器所需的参数,添加对应的属性到子类中,默认层级都是同一级,子类可重写fl_remotePushModel方法,对应不同的字典转模型
 *
 *  注意一点:子类中所添加的属性,应该都为对象,基本数据类型不行喔,而且后台返回的都是对象,基本数据用NSNumber包装
 */
@interface FLRemotePushModel : NSObject
/**
 *  @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;

@end

@interface FLRemotePushManager : NSObject

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

@end

4.实现

大概思路:根据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;
    }
}

5.调用

- (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]];
}

6.总结

  • 先放好个传送门 gitHub 地址 喜欢给个like 和 star 呗~
  • 注意点:必须跟后台配合,定好规则,哪条推送消息需要跳转到哪个控制器、以及该控制器中请求后台所需的参数都要返回给客户端,归根到底还是利用了OC的运行时特点,可以获取对象以及对象属性、方法,最后还是给个效果图吧~

auto push.gif


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值