iOS 如何动态切换 APP 的主题

       主题的切换就是可以增强用户体验、结合运营活动的一个点:譬如 QQ 的夜间模式,节日里电商 APP 的皮肤切换等等的这些小细节往往就是赢得用户尊重的根本。

       让 APP 已有的控件能切换主题可以用子类化,swizzle 或 category 来实现,其中子类化和 category 实现起来差不多,都是让控件调特定的方法达到切换风格的效果,而 swizzle 的影响范围会比较广,使用的时候可以通过 Associated Object 添加一个标记值,让需要切换风格的控件设置这个标记值,让标记值来决定是否需要 swizzle。考虑到上述几种方案的复杂度,最后选择了 category 来实现。

       主题管理类的核心功能就是负责主题的更新,切换。正如下图所示,想让主题管理类通知到这么多待切换的 category 并不是一件容易的事,因为觉得在 category 上添加观察者并不是太好的设计,你很难知道什么时机该把观察者移除了。

主题管理类

这也就意味着,可能需要自己动手来实现回调机制了,让切换主题相关的 category 通过主题管理类注册一个回调 block,主题类维护使用一个字典维护这些 block,待切换时由主题管理类统一回调,达到类似 Notification 的效果。

UILabel的categroy

categroy

只是在方法的底部添加了注册 block 的方法,而注册 block 的方法也十分简单,只需依据 key 判断下是否需要将 block 加入代码中。

那么问题来了,到底该如何设计一个这样的 key 呢?

同一个控件的主题 category 有多个需要切换主题的方法(例如 UIButton 有setTitleColor:forState: 和 setImage:forState:);

多个控件都是通过同一个 categroy 来切换主题(例如有多个 UIButton 需要切换主题);

其实统筹来看,就是如何通过某个类的实例和所需定制主题的方法来确定一个 key。

一开始很自然的拼了一个类的地址和方法名来作为key[NSString stringWithFormat:@"%p#%@", class, NSStringFromSelector(selector)]

流程能跑起来了,但是问题也很明显,只知道一个对象的指针字符串,根据对象是否被释放而进行的字典清理将变得难以实现:

切换主题

那么,应该怎样设计 block 对应的 key 呢?

能从 key 中获取到注册的类;

key 中也存有方法做 key 的唯一性和对象访问该方法安全性的校验respondsToSelector;

为此,实现了一个辅助的 model,用以访问需要注册的对象实例和方法名,同时作为 Dictionary 的 key,它还需要实现 NSCoping 协议:

ThemeMapModel.h


weak 修饰的对象实例能够在对象被释放后自动置 nil,下面附上最初的.m文件实现。

ThemeMapModel.m

效果图


1.gif

总结

       本文描述了实现一个主题管理类的大致思路,希望能对读者有所帮助。后来笔者想到既然有了 target 和 selector,能不能通过 NSInvocation 来动态调用,就不借助 block 来回调了,在尝试中笔者 NSInvocation 的效率的确会低一点。用 block 可以很灵活的指定好需要调用什么方法。或许,也可以通过实现一个 weak proxy 的方式使用 Notification 来实现,笔者就没有尝试了,感兴趣的读者可以试试。

源码地址:https://github.com/AlbertXYZ/ThemeDemo

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

推荐阅读更多精彩内容