iOS客户端节日换肤的思考与实现

作者: Agenric | 来源:发表于2016-12-13 23:00 被阅读1442次

最近单位的APP来了新的需求,市场说他们要在圣诞节把APP里的图标都换了,还要换背景图片,还要给部分view添加一个遮盖。对,就是换肤。以前没有搞过换肤,所以考虑了一天,感觉大概就是这么个思路,感觉有问题的大家可以一块讨论。

总体来说主要分为两个部分:

  • 第一部分主要是服务器资源的远程加载:
    资源加载.png
    先说一下我们的要求是,一般在活动的前一天或前几天会提前把资源准备好放在服务器,然后后台开启换肤的接口,也就是说争取在活动开始前确保大多数用户已经把节日需要的资源下载到了本地,然后服务器接口返回会有此次活动的开始时间以及结束时间。然后在活动期间用户打开APP的话动态更换资源。暂时不考虑极限情况,例如用户在活动开始之前始终没有打开过APP,那么该用户当天打开APP第一次是不会看到最新的皮肤。
    流程图是刚开始考虑的时候按着当时的思路画的,具体实现的时候有些许偏差,不过总起来说就是这个逻辑。在APP初次打开时配置关于皮肤的一些参数信息比如说我们默认把起始时间都定为1970年1月1日,把活动id定为0,以后递增反正自我发挥,只要能确保与之后服务器的数据做对比,之后再次打开时只是去读取之前存好的值,在这里我会有一个换肤服务的一个单例,提供一个只读属性来标示现在是否需要更换资源。
@interface ChangeSkinService : NSObject

// 是否允许更换资源
@property (nonatomic, assign, readonly, getter=isShouldChangeSkin) BOOL shouldChangeSkin;

+ (instancetype)sharedInstance;
- (void)configService;
- (NSString *)resourceFile;
@end

如果服务器的版本高于本地的版本,则证明可能有换肤活动,这时需要判断服务器活动的结束时间,如果这个时间早于当前时间说明这次活动可能已经过期,那么客户端也就没有下载资源的必要了。如果这个时间晚于当前时间,则需要下载资源,这里可以给一个资源状态的标示,用来以防本地的版本已经跟服务器的同步而资源并没有下载成功的意外情况。事实上,我们可以一直等到资源下载并解压完成后再更改本地的所有设置,中间如果发生不可预料的错误,也可以避免客户端本地产生脏数据。

  • 第二部分主要就是图片资源的加载了:
    图片加载.png
    这部分基本上没什么操作难点,无非就是运行时更改+ (nullable UIImage *)imageNamed:(NSString *)name;方法,重写该方法,在ChangeSkinService单例允许更换资源的情况下,去本地沙盒的Document文件夹中读取需要的图片。具体细节可以根据各自业务的不太来制定,大致思路是不变的,比如说你客户端有的地方的图片可能会有拉伸之类的需求,但这样其实是不影响的,因为图片拉伸的操作底层依然需要调用imageNamed:方法来找到该图片。
    所以,基本也就这样。如果你有问题也可以留言我们一起讨论。

注:此文章首发在简书转载请说明出处。
如果你想看到完整的代码,可以去这里

相关文章

网友评论

  • 随行的羊:希望关注 “iOS开发知识小集” 的专题哈,谢谢:smile:
  • 豆豆哥哥:兄弟 麻烦问一下 颜色怎么换掉的
  • ce7871d40869::blush: 刚好有这样的需求,过来参考一下
  • 菲皇:兄台你好,之前我公司有一个换肤需求和你的一样,看过你的代码了,zip包资源下载解决了我图片同步的问题,我之前是返回图片链接,本地实现批量下载、同步渲染;我的实现思路:皮肤管理单例暴露动态渲染的接口,管理类HashTable弱引用外部view设置图片、颜色的代码块以及view,当需要换肤时只需要遍历弱引用集合,刷新view;当需要换回默认皮肤时,只需要执行一遍block。这样子就解决了一定要第二次进入app才能换肤的问题,而对于显示什么主题,什么时间段显示,完全由服务端控制,图片version为0时展示默认主题,version递增显示不同活动皮肤,这样子是不是本地就不需要维护时间段,防止用户修改系统时间导致皮肤恢复默认。
    Agenric:恩,我了解到了。刚开始设计时我们也有这样的考虑,然而产品说他们接受不了屏幕上一闪而过的换图操作,嗖。。。。就此作罢:joy:
  • 神龍大俠:本人愚见 :我观察到 主流的app不都是有活动时发布新版本的吗?何况也不知道产品经理具体什么需求,那些地方要加,那些地方要改。 其次我观察到一些app在有重大活动时,首页布局改动很大,活动结束又恢复如初,这是有两份代码在维护么?动态换肤和所谓的“热修复”是不是有关系,像标签栏上的图标不都是放在本地资源包里的么,这个怎么动态更换呢?ios新手,望解惑
    Agenric:@神龍大俠 首先,第一点,本地资源包放图片是放一些APP内的图标啊背景图片啊之类的,但是事实上除了icon之外我们可以什么都不放,因为你可以使用网络请求把所有素材下载到需要他的地方,当然没人会这样做。
    动态换肤简单的说,基本的动态换肤其实没有你想的那么复杂,无非就是过年过节的时候更换一些按钮的图标,一些视图的颜色或是背景图片之类的,这些东西有经验的产品自然会在设计的时候考虑到,不会说让你开发去一次一次的改。
    说到主流,事实上我也仅仅是观察过而已,类似天猫,他的TabbarItem包括个人中心的部分item我感觉应该是直接走的链接,并且没有做缓存。因为你杀掉APP之后重新打开,item会默认显示资源包里的图片,等待下载好远程图片之后会替换过来。
    至于热修复,适用的场景更多是代码层面的,bug修复、不发新版做到热更新,个人感觉跟动态换肤联系不大。
  • 912e4b7eca99:这个方法有一个问题那就是下载图片是异步的,这可能会导致有些图片替换了,但是有写没有替换。
    Agenric:@NewsQuan 这个问题我有考虑到但是没有在文中写,你可以换肤的单例持有一个集合,这个集合里添加资源包下载成功之前已经加载过图片的view,等到下载并解压成功之后,遍历这个集合中的view去重绘,即可实现。目前是这样考虑。。。
  • YxxxHao:你可以看下我写的统一主题管理文章,在我那机础上加个动态开关就可了,就算等一次打开也没问题
    YxxxHao:@Agenric 时间直接从服务器获取,换肤可以可以加动态开关,主要是下载资源的策略
    Agenric:@YxxxHao :+1: 谢谢分享,刚刚看了。只不过我这个其实需求并不是那么明确,比如说并没有确定整个应用共有多少套皮肤,而仅仅是在节日或特定的时间去强制更换资源,并不是用户主动去换肤。所以需要控制时间,然而 到现在并没有一个非常行之有效的方法来保证客户端与服务器的时钟是同步的。。。

本文标题:iOS客户端节日换肤的思考与实现

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