美文网首页iOS开发的正确姿势iOS 开发 Runtime
河狸家APP如何满足产品的任意页面跳转需求(runtime)

河狸家APP如何满足产品的任意页面跳转需求(runtime)

作者: 咸鱼的技术博客 | 来源:发表于2016-07-06 00:53 被阅读1083次

    一 跳转native页面需求入口来源分析

    跳转native页面的源头分五类:

    1.第三方app唤起跳转,包含短信;这类多用于第三方市场商务合作以及运营活动;

    2.推送消息指令跳转;这类可帮助运营提高老用户活跃,提高转化;

    3.服务器下发指令跳转;(长链接场景服务端主动推消息)

    4.App native内部跳转;iOS自身技术设计需要;

    5.native与h5的交互跳转;在电商app中,十分广泛,可帮助产品更快试错,更快速的迭代更新;

    分析了来源和意义,我们来看看电商app实现任意入口的任意跳转到底有什么好处呢?

    二 电商app实现任意跳转app页面的好处

    1.从产品上:服务端即可灵活的控制app,满足产品天马行空的跳转想象,更灵活的满足产品需求;

    2.从运营支持上:我们要明白任何没有着落页的短信及推送消息,都是耍流氓,否则对点击了消息而没有看到着落的用户就是一种伤害;而它能解决点击每个活动消息都可以自定义着落页面;

    3.从技术上:当两位领导意见分歧,一个要跳a页面,一个要跳转到b页面,此时则可搞a/b test,再结合BI数据分析,分析转化;最终帮助公司沉淀最优方案,提高转化,最终实现理想IPO上市;这就是技术的力量(哈哈平和领导的关系,维护了公司的团结稳定#共勉#)

    估计大部分技术都没有意识到自己还有这种力量,以上对话勿让领导听到#奸笑#

    这样看起来无论哪个入口要跳转哪个页面,技术上去做好它都变得十分有意义!

    三 河狸家app早期协议

    (因安全原因,由于苹果可通过class-dump命令,反编译处理,若直接暴露类名/方法/对象会引来安全问题,故以下代码的方法和类名都经过处理,命名也不规范,请谅解,注意思路)

    背景:

    设计理念,如同http://访问一样,只需要一个知道Url抛给底层服务,即可访问想要到达的页面,而上层工程师不需要关注中间如何访问及如何跳转;

    由此,河狸家app定义了一个openUrl,来控制所有的页面跳转访问;

    下面来看openUrl结构:

    首先要建立协议:

    1.协议头定义:考虑到第三方app唤起的原因,我们将协议头定义为URL Schemes(如微信的weixin://),这里考虑到安全问题,则隐藏河狸家app URL Schemes;用“HLJ://”代替

    ~urlString 形如 @"HLJ://page?jsonData={json}";

    ~1、区分事件类型 如"page"

    ~2、获取json

    json对象结构形如

    {

         "hljType” : enum, //跳转页面标示   建立一个页面映射表来对应enum

        “hljPageN” : “作品详情”,//页面名称

        “jData” : {

                “proId” : “sldkjf3l2”

          }

    }

    json对应的model对象ScEntity如图:

    制定完协议结构,下面来看看过程核心代码结构:

    核心管理类ScManager,负责接收openUrl协议,校验协议,解析json,定向跳转;

    工程师在开发过程只需要注意在openurl中填写跳转目的页面,以及model丢出数据即可,其他则不用关注;

    第一步

    首先校验跳转协议,必须要遵循HLJ://才可进入跳转逻辑,否则认为非法;

    再解析jsondata,并解码son串;

    第二步

    将json解析成字典,利用MJ将数据转成SceneBaseEntity对象

    第三步,通过枚举映射表对应跳转类,并拼接model

    再利用

    再通过

    TabBarController *rootNav = (TabBarController *) kWindow.rootViewController;

    [[rootNav.viewControllers objectAtIndex:rootNav.selectedIndex] pushViewController:controller animated:YES];

    实现了跳转;

    优点:

    1.直观;

    2.工程师编码只关注目的,和对应的唯一model。

    缺点:

    1.它还是不够灵活,每个页面都需要在枚举表中对应上映射,无法做到不发版本即可跳转无映射的页面;

    2.当项目逐渐扩大,页面无穷多个时,产品的野心也在膨胀后,要写一堆的switch判断;

    那还是不完全满足啊~~~~

    别急!!!!来看第四段~~~~~

    四  如何设计一套协议另app能够自由任意的跳转呢?

    核心:runtime运行时机制+组件化

    (这里插个题外话,无论老人代码写的怎么样,都是带动的创业公司走过风雨,尊重与感谢,勿吐槽多敬重!!!)

    注意:由于旧工程需要兼容,还考虑这套设计中的openurl协议涉及安卓/iOS /前端/后端,考虑团队,则需要一个过渡方案。于是只能在旧工程上switch case,并且为了兼容旧版本,最新的运行时动态跳转设计中添加了一个enum为PgType_Runtime=100;来判断走新的跳转机制;

    并且我们的ScEntity增加了三个属性 cname/mcname/moname

    而我们的openUrl所对应json结构也发生了如下变化;

    ~1、区分事件类型 如"page"

    ~2、获取json

    json对象结构形如

    {

         “type” : enum, //跳转页面标示   建立一个页面映射表来对应enum

         “pgName” : “作品详情”,//页面名称

         “cName” : “ViewController”,//页面class名

         “mCName” : “Model”,//model class名

         “mOName” : “model”,//model对象名

         “jdata” : {

                  “proId” : “sldkjf3l2”

           }

    }

    例如要跳转作品列表:

    "openUrl": "hlj://pg?jData={\"hljtype\":100,\"cName\":\"SearchtResultController\",\"mCName\":\"SeachCModel\",\"mObjName\":\"searchC\",\"pgN\":\"作品列表\",\"data\":{\"artType\":1,\"cate\":\"tag_m\"}}}"}"

    第一步,

    通过cName,获取cName所对应的类名pageclass,通过pageclass创建唤起的目标页面对象;

    第二步,

    通过mcName去获取mcName所对应的类名modelclass;

    再通过objc_getClass(modelclass)获取modelclass的isa指针指向(唤起的目标页面)所对应的modelc类对象;

    假如不存在modelc类,就去创建一个nsobject类,nsobject是对象的root类;([NSObject class]只是返回一个NSobject类),那么superClass为一个NSobject类;

    使用objc_allocateClassPair为"class pair"分配空间,来创建一个NSobject子类;

    (什么是“class pair"? objc_allocateClassPair只返回一个值:Class。)

    (拓展:如果想要为类添加方法可使用class_addMethod添加了一个方法,如class_addMethod(superClass, @selector(report), (IMP)ReportFunction, "v@:");

    @selector(report)获取一个SEL类型,IMP是oc实现代码块的地址,类时函数指针,通过他可以直接访问人意一个方法,免去发送消息的代价;imp(对象自己(self),方法标示SEL,第三个是方法的参数);通过IMP直接调用方法 等效调用:[self SEL:参数];   //另外增加实 例变量用class_addIvar)

    注册你创建的这个类,使其可用;

    第三步,

    遍历外部传入的参数data的key;

    利用kvc对model对象每个属性进行赋值;

    伪代码表现model.key = obj;//大致是这样一个形式

    且要注意一定要去判断key所对应的model中的属性(名字与key一致)是否存在;(方法在最后代码片段里)

    这样就得到一个完整数据的model;

    第四步,

    model也是一个page页面的属性,则可以同样的方式将model赋值给pageclass

    最后为检查属性是否存在的代码片段:

    这样就愉快的做到了在不发布版本的前提下实现任意跳转;

    五 技术上总结

    协议跨平台兼容性:安卓也是走的同样的一套设计协议,这样安卓iOS都不需要发布版本则可以做到实现任意页面跳转;

    架构提升:对团队工程师的模块化/封装性的要求比较高,提升app的架构设计;

    开发工程师开发成本:不需要关注如何跳转,只需要调用一段代码,将想要到达的目的页面class以及传递的数据model告知给消息中心即可;

    解除模块间的耦合;

    相关文章

      网友评论

      本文标题:河狸家APP如何满足产品的任意页面跳转需求(runtime)

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