移动应用的开发中,有时咱们会须要例如更换皮肤此类的功能,andorid采用xml配置UI的方式,这个问题或许还容易解决些,iOS的主要UI逻辑则是在代码中控制的,若是没有一个强大的框架方案,这个问题将变得很是棘手。网上也有不少诸如此类功能的优秀案例与框架,在这篇博客中,我与你们分享下个人解决方案,其中若是有不恰或者糟糕之处,但愿与高人一块儿交流。框架
首先个人设计思路是采用通知的方式,原理能够以下理解为如下几步:post
一、在系统的通知中心注册一个通知优化
二、全部须要更改皮肤功能的controller做为这个通知的监听者ui
三、设计一个皮肤的model类spa
四、将controller中有关皮肤设置的属性从model中取设计
五、在切换皮肤前更改皮肤modelcode
六、发送更改皮肤的通知orm
上面的6个步骤是这整个框架的基本逻辑,框架无非是将这些逻辑进行优化与封装。下面这张图很烂,可是思路很清晰:server
首先最上面是我设计的一个切换主题的manager,我这里的设计有个缺陷,我将manager和主题配置相关的model混合在了一块儿,写的时候简单了些,可这给框架的逻辑上带来了混乱,因此我在图中使用曲线和虚椭圆将其分离,manager来控制切换model的属性,咱们在controller中取model的属性进行配置,这个manager的逻辑位置是交互时间与通知中心的桥梁。manager中的核心代码以下:xml
//单例方法 +(instancetype)sharedTheSingletion{ static YHTopicColorManager * sharedModel = nil; static dispatch_once_t predicate; dispatch_once(&predicate, ^{ sharedModel = [[YHTopicColorManager alloc] init]; }); return sharedModel; } //这个方法应该分离在model中,从本地读取当前的主题模式,更改后咱们只须要更改本地数据 而后从新调用这个方法便可 -(void)getTopicModel{ //从本地读取 int tp = [YHSASystemSettingManager sharedTheSingletion].topic; if (tp==0) { //默认为白天主题 tp=dayTime; [YHSASystemSettingManager sharedTheSingletion].topic = tp; } switch (tp) { //这里是我定义的一些枚举,拿白天和夜间模式示范 case dayTime://白天模式 { //这里面定义一些白天模式下 控件的颜色属性 也能够定义其余 _navColor=[UIColor colorWithRed:10/255.0 green:85/255.0 blue:160/255.0 alpha:1]; _bgColor=[UIColor colorWithRed:1 green:1 blue:1 alpha:1]; _btnColor=[UIColor colorWithRed:10/255.0 green:85/255.0 blue:160/255.0 alpha:1]; _textColor=[UIColor colorWithRed:0 green:0 blue:0 alpha:1]; _btnTextColor=[UIColor colorWithRed:1 green:1 blue:1 alpha:1]; _navTextColor= [UIColor whiteColor]; } break; case nightTime://夜间模式 { //这里面定义夜间模式下的相关控件的颜色属性 _navColor=[UIColor colorWithRed:10/255.0 green:85/255.0 blue:160/255.0 alpha:1]; _bgColor=[UIColor colorWithRed:0 green:0 blue:0 alpha:1]; _btnColor=[UIColor colorWithRed:10/255.0 green:85/255.0 blue:160/255.0 alpha:1]; _textColor=[UIColor colorWithRed:1 green:1 blue:1 alpha:1]; _btnTextColor=[UIColor colorWithRed:1 green:1 blue:1 alpha:1]; _navTextColor= [UIColor whiteColor]; } break; default: break; } } //发送更改主题的消息 +(void)postTopicChangeMessage{ [[NSNotificationCenter defaultCenter]postNotificationName:YHTopicChangeTopicNotication object:nil]; }
在manager调用通知中心发送通知后,咱们要让全部须要改变主题的视图控制器都接收到通知,最简便的作法是,咱们设计一个父类,让父类监听通知,全部须要有主题更改功能的控制器继承于它便可,这个father controller的核心代码以下:
//移除监听 -(void)dealloc{ [[NSNotificationCenter defaultCenter]removeObserver:self]; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. //添加监听主题更换的通知 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(useYHTopicToCreatViewWithModel) name:YHTopicChangeTopicNotication object:nil]; //协议中的方法,加载主题 一会再说 [self useYHTopicToCreatViewWithModel]; } //子类实现以下方法 -(void)useYHTopicToCreatViewWithModel{ }
到目前,咱们已经能够顺利接收到主题切换的通知,但是要全部子类都步伐一致的执行相同一个操做,咱们能够经过一个协议来约定,这就是图中的主框架的protocol,这个协议中规定一个特定的方法,咱们在父类中调用,子类中实现,当收到通知时,全部子类都将从新加载这个方法,若是咱们将皮肤设置部分在这个方法中实现,那么正是咱们想要的效果,全部皮肤设置都被从新加载了。协议以下:
/** *这里定义主题的风格 */ typedef enum { dayTime=1,//白天 nightTime//夜间 }YHTopicModel; @protocol YHTopicProcotol <NSObject> //全部能够更换主题的界面必须遵照这个协议调用并实现以下方法 //将视图中控件的颜色摄住部分所有放在这个方法中 @required -(void)useYHTopicToCreatViewWithModel; @end
这时,就剩下咱们这套逻辑的最后一步了,咱们只须要将控件的颜色设置写在子类的协议方法中,而且,这些设置的数据来源于model这个模型,整个体系就完成了,子类实现方法以下:
-(void)useYHTopicToCreatViewWithModel{ //获取到模型 YHTopicColorManager * model = [YHTopicColorManager sharedTheSingletion]; //加载模型数据 [model getTopicModel]; //进行设置 self.view.backgroundColor = model.bgColor; _schoolLabel.textColor = model.textColor; _phoneLabel.textColor = model.textColor; _secertLabel.textColor = model.textColor; _reWriteSecretLabel.textColor = model.textColor; _questionLabel.textColor = model.textColor; _answerLabel.textColor = model.textColor; _registBtn.backgroundColor = model.btnColor; [_registBtn setTitleColor:model.btnTextColor forState:UIControlStateNormal]; }
我简单写了一些界面,不论任何地方切换皮肤,全部界面效果都会改变:
切换夜间模式前:
开启夜间模式后:
本身的思路实现更换主题的一种方法,真诚的想与志同道合的朋友交流开发经验,若是你想批评,点拨,交流或者是借鉴个人代码,Q316045346随时欢迎。
专一技术,热爱生活,交流技术,也作朋友。
——珲少 QQ群:203317592