全部三个宗旨风格、差异的读书方式(日间澳门永利234555com/夜间),在此提前谢谢)

如果你有更好的想法,拥有多个主题风格、不同的阅读模式(日间/夜间)

若是你跟自个儿同样,工作了一年半,相信您也经历过多少个大版本的迭代开发,甚至具备多少个利用的费用经历。那么在促成过那么多复杂的政工逻辑之后,你以为,利用纯代码,如何去创建四个美、优、简以及便于管理的为主框架呢?
那二日在思索这一个题材,于是有了以下想法(可能还不是很干练,若是你有更好的想法,请评论告知本身,在此提前谢谢)。

捋捋思路

撸撸思路

后天以搭建贰个连串的主导框架为例,来探究这几个难题,最后的效能图如下:

澳门永利234555com 1

展示效果

世家能够看看,那确实是一个犬牙相制项目标底蕴,固然逻辑再繁杂的界面,最初始也都以从这么些界面起步的,而对此它,大家必要做的:

  • 开头化多少个子控制器
  • 添加自定义的 TabBarView
  • 添加自定义的 NavigationBar
  • 添加自定的 TopBarColumnView
要落成怎么样的职能?

澳门永利234555com 2

TogglingReadingMode

Demo
https://github.com/iJudson/RxReadingMode

预备工作

此处主就算准备一些体系支出须求的资源和添加一些亟需选拔到的第1方库,进程大约、琐碎:

  • 导入须要使用到的百分之百图形财富
  • 导入供给采纳到的第①方: 普拉多xSwift、CRUISERxCocoa
  • 结缘 UIStoryBoard
    初步化多少个控制器,并在种种控制器上添加发轫化呈现图片

实现上述操作之后,可得项目结构如下:

目录名称 功能介绍
Main 项目的主要入口
Main – MenuViewController 菜单控制器,作用与 TabBarController 相同
Business 存储所有的业务逻辑模块
Business – Home 首页业务模块
Business – Medium 书影音 业务模块
Business – Broadcast 广播 业务模块
Business – Group 小组 业务模块
Business – Profile 我的 业务模块
Utility 存储所有的功能模块
Utility – Extension 存储所有功能类的功能扩展

本来,大家认为无聊就径直跳过这几个操作,在 github 上
https://github.com/iJudson/RxBasicInterface.git
<后期准备> 该 commit 上平素获得这一步的代码

应用地方

八个采纳,为满意用户多变的私欲,拥有八个核心风格、差异的开卷情势(日间/夜间),那种景观喜人,像某易某音乐,就同时具备本性换肤和夜间格局的效果

澳门永利234555com 3

某易某音乐-夜间形式-天性换肤.JPG

但尽管二个应用拥有再多的风格,本质无非是预先准备好那几个分裂风格的「颜色样式」、「图片样式」、「遮罩样式」而已,当您点击调整风格的按钮,全体必要替换风格的界面收到文告之后,获得事先准备好的样式实行替换即可。

正题

终止了具有的备选干活,接下去进入正题:使用 HighlanderxSwift 创制 TabBarView
供菜单控制器 MenuViewController 使用

落实格局

总的来说,大家须要监听者去监听「格局切换的按钮」,当接到到用户的点击时,通告全数界面,启用另一套大旨风格。由此,大家要求利用到监听方式,由于涉及到多个界面差别层次下的监听,大家听其自然会化解「Delegate」 和 「Block」那二种监听情势,那么在非 Reactive
下,我们也不得不使用通告中央那种监听方式了,但其实若是使用 Reactive
,会不难得专程多,代码质量也会高很多,而且当一个用到具有几13个界面时,大家就不须求无止境的去移除监听者,也不必要操心因为有个别界面忘了移除监听者而带来的夭亡难题,Reactive
中有二个自行移除监听者的效益,会帮我们处理好那么些业务。

TabBarView 的创建

实际对于某个 View
的施用,尽管是本身创设的,往往会在过了一段较长的年华之后,再去选择那张
View 时,竟然发现未能动手,需求再重蹈覆辙下代码,特别是对于那么些专门复杂的
View,有多少个方便构造函数,或许更加多的子控件,而且亟需依照分化景色去行使当中的少数控件…
再有一种景况,
你在商店与其余人协同工作时,会不会意识要去接纳到她创造的比较复杂的 View
时,须要或局地岁月,感到特别烦啊?
本着那三个难题,我的消除方案是:

<创制该 View 专属的样式类>
在那里,你能够先去跟你的同事或跟本身约定一套成立 View
的作风,正是在成立该 View 的时候先去创设该 View 的依附样式类:用于管理该
View 的富有样式:颜色、子控件类型和数据、子控件的来得地点…
咱俩想创立 TabBarView,让大家先来创设 TabBarView 的样式管理类:

typealias TabBarItemElement = (normalImage: UIImage?, selectedImage: UIImage?, title: String?)

// TabBarView 的样式管理类
struct TabBarStyle {
    //  子控件的元素集合   
    var itemElements: [TabBarItemElement]
     //  TabBarView 的颜色主题(默认为白色)   
    var themeColor: UIColor = UIColor.white
    //  是否含有顶部分割线   
    var hasTopLine: Bool = true
    // 在初始化构造器中,只去初始化必要的元素,避免初始化构造器过于冗长
    init(elements: [TabBarItemElement] = []) {
        self.itemElements = elements
    }
}

<创建 TabBarView>
有了下面包车型客车体裁管理类,我们在该 View
中,对外的属性就特别少,基本就唯有五个,那也大程度的增强了该 View
的封装性。
1. 定义对外的体裁属性:

// 主题样式
var themeStyle: TabBarStyle = TabBarStyle() {
    didSet {
        // 通过属性监视器,外部可以通过该属性更新 TabBarView 的整体样式
        update(ThemeStyle: themeStyle)
    }
}

2. 创立便利构造函数:便于外部对此类的利用

convenience init(frame: CGRect? = nil, themeStyle: TabBarStyle) {
    // 当外部不传入 Frame 值时,我们默认使用以下 Frame 值
    let barFrame = frame ?? CGRect(x: 0, y: screenHeight - tabBarHeight, width: screenWidth, height: tabBarHeight)
    self.init(frame: barFrame)
    // 设置背景颜色
    self.backgroundColor = themeStyle.themeColor
    // 根据样式管理类,更新该 view 的主体样式
    update(ThemeStyle: themeStyle)
    // 根据样式管理类,决定是否添加顶部分割线
    add(TopLine: themeStyle.hasTopLine)
}

OK,到此处这一个 View
大体上就创办实现了。是不是相当粗略,日后是还是不是也很便于管理?方今来看,这个View 只有3个对外属性,还有一个 convenience
构造函数,确实很有益于大家管理,而对此样式,大家只须求去查看样式管理类,就只有这个View 的保有的样式…
哈哈,其实接下去,依旧某个细节要接二连三周密。

3. 完结样式更新的方法
在内部,我们只要求得到表面传进来的体裁属性,去创新样式。
因为此处的 TabBarItem
既有图片,又有标题,全部外部供给将那多少个属性都传进来。

fileprivate func update(ThemeStyle style: TabBarStyle) {
    // 所有的样式元素数量
    let itemCount = style.itemElements.count
    let itemWidth = screenWidth/itemCount
    var commonItemFrame = CGRect(x: 0, y: 0, width: itemWidth, height: tabBarHeight)
    // 通过 for 循环,将拿到的所有元素遍历添加到 TabBarView 上
    for (index, element) in style.itemElements.enumerated() {
        commonItemFrame.origin.x = index * itemWidth
        let commonTabBarIem = CommonItemView(frame: commonItemFrame, image: element.normalImage, title: element.title)
        commonTabBarIem.setImage(element.selectedImage, for: .selected)
        commonTabBarIem.alignmentStyle = .upImageDownText(space: 2)
        commonTabBarIem.tag = index
        commonTabBarIem.titleLabel?.font = UIFont.systemFont(ofSize: 12)
        commonTabBarIem.setTitleColor(UIColor.gray, for: .normal)
        commonTabBarIem.setTitleColor(UIColor.black, for: .selected)

        self.addSubview(commonTabBarIem)
        // 这里我们添加监听者,监听每一个 Item 的点击操作,当 item 被点击时,我们通过 Driver 序列,发送点击事情到这和序列上
        let selectedIndex = commonTabBarIem.rx.controlEvent(.touchDown).throttle(0.5, scheduler: MainScheduler.instance).flatMapLatest { (_) -> Driver<Int> in
            return Driver<Int>.just(commonTabBarIem.tag)
            }.asDriver(onErrorJustReturn: 0)
        // 对外监听属性的集合 
        selectedIndexes.append(selectedIndex)

        // 默认选中第一个 tabBarItem
        commonTabBarIem.isSelected = (index == 0 ? true : false)
    }
}

在上边方法中,大家应该有在意到,大家须要一个对外监听属性的集聚,监听用户的点击操作,因为相似
TabBar 有八个 Item,故而那么些集合一般都有七个对外监听属性,属性定义如下:

 //当前选中的 index
 var selectedIndexes: [Driver<Int>] = []

4. 添加顶部分割线

 fileprivate func add(TopLine isExisting: Bool) {
    // 事先判断是否需要添加分割线,如果不需要,可直接 return 返回
    guard isExisting else {
        return
    }

    let lineHeight: CGFloat = 0.5
    let topLine = UIView(frame: CGRect(x: 0, y: -lineHeight, width: screenWidth, height: lineHeight))
    topLine.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.3)
    self.addSubview(topLine)
 }

到这一步的代码,我们能够在
https://github.com/iJudson/RxBasicInterface
<创立 TabBarView> 当前 commit 上获取(注意,今后在那些 commit
上运转程序,依旧没有其它成效,毕竟还未曾应用到该 TabBarView)

NotificationCenter (布告中央)

用作非 Reactive 下的唯一兑现格局,固然真正会比 Reactive
的应用繁琐很多,不过大家还是能让它尽大概的幽雅的,由于那种完结方式并不是自个儿那篇文章的主题,所以本人只尤其不难的切磋自个儿的贯彻思路:

  • 概念通告总宗旨管理器 「NotificationCenterManager」
    行使中具有的通报的拉长和移除都得以因而该总宗旨去管理

  • 概念颜色样式配置主题「ThemeStyleConfigs」
    重在是用来管理不相同风格下的富有重点样式

  • 为所需控件类的 Extension 绑定设值属性
    因而运营时,为 UIView、UIImageView、UIButton、UILabel 的
    Extension,添加绑定三个对外的颜色属性,目标是外表仅必要为该属性的
    set
    方法设置,即可为对应的控件添加监听者,当总得公告中央报告该控件的监听者要求置换另一套颜色样式,即经过体制配置基本得到该控件所需样式举行轮换

TabBarView 在 MenuViewController 的使用

TabBarView 是在 MenuViewController 去选择的, 在 MenuViewController
中也亟需去监听 TabBarView 的 selectedIndexes 数组属性,从而监听到
TabBarView 上的点击操作。而实际,TabBarView 的选择,由于选择了 PAJEROxSwift,也变得专程简单,也方便管理。
1. 大家在 viewDidLoad 添加五个法子

  • 开头化 MenuViewController
    中存有的子控制器,并私下认可让首页控制器展现在主页上
  • 布局底部 TabBarView ,创设所需样式管理类
    TabBarViewStyle,并添加所需成分

 override func viewDidLoad() {
    super.viewDidLoad()

    initializeTopViewControllers()

    configureTabBar()
 }

接下去,大家只供给定义并完善上述七个方法…

2. 初步化全体的子控制器

 fileprivate func initializeTopViewControllers() {
     // 通过 UIStoryboard 拿到所有的子导航控制器
    let homeNav = UIStoryboard.NavigationController.home
    let mediumNav = UIStoryboard.NavigationController.medium
    let broadcastNav = UIStoryboard.NavigationController.broadcast
    let groupNav = UIStoryboard.NavigationController.group
    let profileNav = UIStoryboard.NavigationController.profile
    // 并预先添加到 topViewControllers 数组中,当点击某一个 TabBarItem 时,根据需要添加具体的控制器
    topViewControllers = [homeNav, mediumNav, broadcastNav, groupNav, profileNav]

    // 初始化时,默认添加首页控制器
    self.addChildViewController(homeNav)
    homeNav.view.frame = self.view.bounds
    self.view.addSubview(homeNav.view)
    // 默认显示首页控制器
    self.selectedViewController = homeNav
    // 更新状态栏的状态
    self.setNeedsStatusBarAppearanceUpdate()
 }

3. 配置 TabBarView,监听在那之中的点击属性

  • 我们得到拥有的图样和标题属性
  • 布置 TabBar 样式管理类
  • 监听TabBarItem 的点击操作(那里由于 ENCORExSwift 会变得专程简单)
  • 拍卖 TabBarItem 的点击事件

 fileprivate func configureTabBar() {
    // 拿到五个 BarItem 上的元素(图片和标题)
    let barItemElements: [TabBarItemElement] = [
        (normalImage: UIImage(named: "ic_tab_home_gray_32x32_"), selectedImage: UIImage(named: "ic_tab_home_32x32_"), title: "首页"),
        (normalImage: UIImage(named: "ic_tab_subject_gray_32x32_"), selectedImage: UIImage(named: "ic_tab_subject_32x32_"), title: "书影音"),
        (normalImage: UIImage(named: "ic_tab_timeline_gray_32x32_"), selectedImage: UIImage(named: "ic_tab_timeline_32x32_"), title: "广播"),
        (normalImage: UIImage(named: "ic_tab_group_gray_32x32_"), selectedImage: UIImage(named: "ic_tab_group_32x32_"), title: "小组"),
        (normalImage: UIImage(named: "profile_normal_32x32_"), selectedImage: UIImage(named: "profile_active_32x32_"), title: "我的")
    ]
    // 创建管理样式类
    let tabBarStyle = TabBarStyle(elements: barItemElements)
    // 拿到样式类,创建 TabBarView 
    let tabBarView = TabBarView(themeStyle: tabBarStyle)
    self.view.addSubview(tabBarView)
    // 监听 TabBarView 的 selectedIndexes 属性,当有点击操作时,触发处理点击事件的方法
    for selectedIndex in tabBarView.selectedIndexes {
        selectedIndex.drive(onNext: { [weak self] (index) in
            guard let strongSelf = self else {
                return
            }
            // 处理点击事件
            strongSelf.handleTopControllerSelectionEvent(currentIndex: index)

        }).disposed(by: disposeBag)
    }
 }

而其点击事件的拍卖如下:

fileprivate func handleTopControllerSelectionEvent(currentIndex: Int) {
   // 移除上一次选择的控制器
    if let selectedViewController = selectedViewController {
        selectedViewController.willMove(toParentViewController: nil)
        selectedViewController.view.removeFromSuperview()
        selectedViewController.removeFromParentViewController()
        selectedViewController.viewWillDisappear(false)
    }
    // 添加当前选择的控制器,并显示
    let currentSelectedViewController = topViewControllers[currentIndex]
    self.addChildViewController(currentSelectedViewController)
    currentSelectedViewController.view.frame = self.view.bounds
    self.view.addSubview(currentSelectedViewController.view)
    currentSelectedViewController.didMove(toParentViewController: self)
    self.selectedViewController = currentSelectedViewController
    self.setNeedsStatusBarAppearanceUpdate()
    self.selectedIndex = currentIndex

    // 置顶 TabBar
    for subView in self.view.subviews {
        if let tabBar = subView as? TabBarView {
            self.view.bringSubview(toFront: tabBar)
        }
    }
}

OK,到那里,我们二个简约的门类框架就曾经实现,其遵从如下:

澳门永利234555com 4

BasicInterface.gif

您能够在
https://github.com/iJudson/RxBasicInterface
<TabBarView 在 MenuViewController 的使用>
的道岔上获得于今的代码。

RxSwift
  • 运用 CocoaPod 将第2方框架 奇骏x斯威夫特 、帕杰罗xCoCoa 引进项目中
    pod ‘RxSwift’, ‘3.6.1’
    pod ‘RxCocoa’, ‘3.6.1’
    pod ‘奇骏xDataSources’, ‘1.0.4’ // 如若界面上有
    UICollectionView/UIScrollView ,则需引入该第叁方
    详情请见 Reactive
    地址:https://github.com/ReactiveX/RxSwift

  • 体制管理配置类
    首借使用来管理项目中保有区别风格的体制,再多的体制,外部都不去过问,而小编辈只供给在此类中去布置即可

  • 体制风格获得类
    顾名思义,该类的是用于出口某种现实的样式。而要输出某种样式,那么大家的做法是,首先为此类输入分歧的品格样式,不过再依照须要,输出在那之中的一种我们必要的样式

    举手之劳发现

    1. 在此类中,大家必要加上多少个监听者,告诉我们:项目当前急需哪一类体制(如:是大白天的体制,依然夜间的体裁)
    2. 在此类,大家也供给提供二个可被考察的样式属性,外部观望并得到该样式属性为控件赋具体样式值
  • 体制调节器
    首要样式调节的开关,控制样式的输入,当须求调剂形式转变时,我们只须要控制分歧的体裁输入,即可达到方式转换的目标
    说到此处,你大概不知所云吧?可是没事,大家先进入实战,以往再回头精晓以上内容,届时,你对这一个形式设计的通晓应该也会愈发深远。

后续

本来贰个简短的品类框架还不止那几个或者会有:

  • 导航栏 – NavigationBar
  • 顶部选用栏 – TopBarColumnView

而那四个 View 的创导跟 TabBarView
的创建是一模一样的,我们都试着去创制体会下。小编那里也不再赘余,而最后的作用如下:

澳门永利234555com 5

Last Version BasicInterface.gif

末段的代码,我们能够在
https://github.com/iJudson/RxBasicInterface
中找到。

如若那几个大旨框架还有哪些地点能够一而再优化,请不吝评论告知本人。
一旦你觉得这几个中心框架还不易,欢迎 star。

感谢!

采纳 福睿斯x斯维夫特 营造阅读格局(日间/夜间)

咱俩以创设1个享有二种风格的翻阅情势为例,而多样品格的施用皮肤,与此基本是一模一样的,无非是多准备一套风格罢了。

一部分再熟稔可是的基本配备

健康来说,MVVM 本就为 奥迪Q3x斯维夫特 而生,项指标设计方式最好选用 MVVM
格局去设计,然则那里的主心骨是读书形式的构建,为了节约大家的理解时间,大家得以稍微简单无情些

  • 创建 RxReadingMode 项目
  • 在 该项指标 Main.storyBoard
    上助长全部须求添加夜间格局的控件,并连线到代码 ViewController 中
  • 导入 Reactive 框架
    pod ‘RxSwift’, ‘3.6.1’
    pod ‘RxCocoa’, ‘3.6.1’
  • 在 ViewController 中添加头文件
    import RxSwift
    import RxCocoa
    成功上述步骤之后,大家运营下项目,确认保障这一名目繁多操作下来是尚未此外难题的:

澳门永利234555com 6

初步化状态

Good!没有啥难点!到此处,大家早就做到了 一成了。而须要添加夜间格局的控件大家曾经准备好了,接下去是不是为那么些控件准备差异格局下的体制呢?

体制管理配置类

咱俩要求预备两套样式:日间格局和夜间方式。为了方便管理,大家定义样式管理类
ThemeStyleConfigs,再在内部经过结构体定义日间和夜间这两套样式:

/// 夜间模式下的样式配置
struct NightTime {
    // 主背景颜色
    static let primaryBackgroundColor = UIColor(red: 33/255.0, green: 33/255.0, blue: 33/255.0, alpha: 1.0)
    // 大标题文本颜色样式
    static let titleTextColor =  UIColor(red: 191/255.0, green: 191/255.0, blue: 191/255.0, alpha: 1.0)
    // 小标题文本颜色样式
    static let detailLabelTextColor = UIColor(red: 140/255.0, green: 140/255.0, blue: 140/255.0, alpha: 1.0)
    // 返回按钮图片样式
    static let backButtomImage = UIImage(named: "night_BackArrow@24x24")

}

/// 日间模式下的样式配置 (与以上对应)
struct DayTime {
    static let primaryBackgroundColor = UIColor.white
    static let titleTextColor =  UIColor(red: 63/255.0, green: 63/255.0, blue: 63/255.0, alpha: 1.0)
    static let detailLabelTextColor = UIColor(red: 101/255.0, green: 106/255.0, blue: 113/255.0, alpha: 1.0)
    static let backButtomImage = UIImage(named: "day_BackArrow@24x24")
}

而当大家想拿有个别形式下的体制,即可通过以下措施:

// 如:拿「日间模式」下的主背景颜色样式
let dayTimeColor = ThemeStyleConfigs.DayTime.primaryBackgroundColor

核心的备选干活到那边就停止了,很无聊?别急,我们要开始部分不均等的做事了。

ReadingModeAdjuster – 阅读体验调节器

阅读经验调节器,即打开区别阅读情势的总开关,我们根据封装思想,将一部分繁杂的逻辑封装在类内,有限支撑表面包车型地铁调用代码可读性尽大概的高,而且调用不难;

  1. 概念被外表监听的翻阅情势属性,其重要用以被混清劲风格的样式类(上边会讲)监听,为方便使用,那里定义为类属性

// 默认值为日间模式
 static var readingMode = Variable<ReadingMode>(.dayTime)
  1. 面前说过,那里是读书方式的总开关,即当点击控制器的格局切换开关时,笔者索要去修改
    1 中读书方式的值,当然我们能够直接拿到 第11中学的属性去赋值,不过那样子就将没须要对控制器开放的 Observable
    属性向它开放了,那并不是大家所希望的,那么我们该如何处理吧?我们透过三个对外的类措施:

// 调用该方法,即可修改 readingMode 属性并引起一连串的连锁反应
static func updateStatus(readingMode: ReadingMode = .dayTime) {
    self.readingMode.value = readingMode
}

到此处,实现了此类的配置,但如故总感到少了点什么?这么些类就只有如此点料?大家就像此冷清1个热心肠的
Variable 属性?

MixedStyle – 混合风格取样类

正如前方所说,大家塑造该类的目标是,向该类输入一些两样的风骨样式,该类就机关输出大家所供给的体制,跟自动售货机一样。听起来很复杂,可是事实上很不难。

诶,可是风格类型不是有很各种?我们兴许须要修改图片的背景颜色(UIColor
类型),又或然必要修改 UILabel 的字体大小(CGFloat
类型)。那….?大家那边能够选拔泛型类,该类的品种会在输入三个值的时候分明。

而其实,那几个类须要做的就只有一件业务,正是出口一个切实的风格样式,但是输入这么各个风格样式,大家毕竟要出口哪个种类样式呢?那自然就取决于「上二个操作」被冷落的属性
readingMode,在此类中,大家去监听该属性的生成,怎样的读书格局就输出如何的品格样式。

  1. 概念混合风格类

struct MixedStyle<T> { 
  /// 混合风格类属性

 /// 混合风格类初始化构造器的配置

}
  1. 错落风格类属性的概念

/// 混合风格类属性
var dayTimeStyle: T // 日间模式样式输入
var nightTimeStyle: T // 夜间间模式样式输入

// outPut
var presentedStyle: Driver<T> // 外部输出属性,即呈现给外部的模式样式,因该值仅在纯 UI 下使用,故定义为 Driver
fileprivate let disposeBag = DisposeBag() // 监听者自动销毁器
  1. 掺杂风格类初阶化构造器的安插

 /// 混合风格类初始化构造器的配置
 init(dayTime dayStyle: T, nightTime nightStyle: T) {

    self.dayTimeStyle = dayStyle
    self.nightTimeStyle = nightStyle

    // 默认日间模式 监听阅读调节器的阅读模式属性,当该属性发生变化,即更新 presentedStyle 的值
    presentedStyle = ReadingModeAdjuster.readingMode.asObservable().flatMapLatest { (readMode) -> Observable<T> in
        switch readMode {
        case .dayTime:
            return Observable.just(dayStyle)
        case .nightTime:
            return Observable.just(nightStyle)
        }
    }
    .asDriver(onErrorJustReturn: dayStyle)
 }

到这一步,我们就全盘把部分配置类和管理类准备好了,那么接下去就到了选取这几个类的环节。请移步到控制器类

ViewController-控制器中调用配置管理类

有了前方的布署,其实大家在控制器的选用就变得老大简便,大家供给做的唯有「2件事情」

  1. 将两套样式(日间/夜间)输入到 MixedStyle
    类中,并为该类的出口样式(presentedStyle)添加监听者,当该出口样式产生变化,监听者得到那一个变化值,进行UI 属性绑定操作

// 输入两套风格样式到 MixedStyle 类中
let mixedViewColors = MixedStyle(dayTime: ThemeStyleConfigs.DayTime.primaryBackgroundColor, nightTime: ThemeStyleConfigs.NightTime.primaryBackgroundColor)
// self.view 的背景颜色去监听 MixedStyle 类的呈现风格并进行背景颜色的属性绑定
mixedViewColors.presentedStyle.drive(self.view.rx.backgroundColor).disposed(by: disposeBag)

let mixedImages = MixedStyle(dayTime: ThemeStyleConfigs.DayTime.backButtomImage, nightTime: ThemeStyleConfigs.NightTime.backButtomImage)
mixedImages.presentedStyle.drive(self.backButton.rx.normalImage).disposed(by: disposeBag)

let mixedTextColors = MixedStyle(dayTime: ThemeStyleConfigs.DayTime.titleTextColor, nightTime:  ThemeStyleConfigs.NightTime.titleTextColor)
mixedTextColors.presentedStyle.drive(self.modeTitleLabel.rx.textColor).disposed(by: disposeBag)
mixedTextColors.presentedStyle.drive(self.modeToggleLabel.rx.textColor).disposed(by: disposeBag)
mixedTextColors.presentedStyle.drive(self.themeStyleLabel.rx.textColor).disposed(by: disposeBag)

let mixedDetailTextColors = MixedStyle(dayTime: ThemeStyleConfigs.DayTime.detailLabelTextColor, nightTime:  ThemeStyleConfigs.NightTime.detailLabelTextColor)
mixedDetailTextColors.presentedStyle.drive(self.modeDetailLabel.rx.textColor).disposed(by: disposeBag)
mixedTextColors.presentedStyle.drive(self.checkButton.rx.textColor).disposed(by: disposeBag)

在那边,有个小插曲:笔者自定义了有的 UI 控件属性监听者,熟谙 智跑xSwift的人恐怕能够很随便看出,因为 EvoquexSwift 这几个第叁方中并从未 UIView
背景颜色监听者,倘诺大家想有个别 UI
属性成为监听者,大家只好去自定义监听者,昂CoraxSwift这么些意义鲜明格外好用,详情可知 Reactive+Extension 类。

///自定义 UIView 背景颜色监听者
extension Reactive where Base: UIView {
    var backgroundColor: UIBindingObserver<Base, UIColor> {
        return UIBindingObserver(UIElement: base) { view, color in
            view.backgroundColor = color
        }
    }
}
  1. 监听 UISwitch 切换开关的操作,当更新 UISwitch
    开关的状态时,咱们相应的一道到 ReadingModeAdjuster 的 readingMode
    属性,还记得以前所说的类措施?

// 当开关打开的时候 开启夜间模式 否则开启日间模式
ReadingModeAdjuster.updateStatus(readingMode: sender.isOn ? .nightTime : .dayTime)

这规范去行使该类,代码的可读性是否高了成千成万,而且也很方便使用?
到那边,我们阅读情势的 德姆o 也就创设形成了,效果图可知文首,而其
Demo
https://github.com/iJudson/RxReadingMode

实在,细心的对象可能发现图片还没添加夜间情势的体裁,那几个三番五次效应我们能够试着完成下,思考如何兑现才为「最优」。

愿意大家在贯彻的长河中也不无收获…