某易某音乐-夜间形式-特性换肤.JPG,在此提前谢谢)

假设您跟作者一样,工作了一年半,相信您也经历过几个大版本的迭代开发,甚至有所多少个使用的支付经历。那么在贯彻过那么多复杂的作业逻辑之后,你认为,利用纯代码,如何去成立3个美、优、简以及便于管理的主干框架呢?
这二日在构思那些标题,于是有了以下想法(大概还不是很成熟,若是您有更好的想法,请评论告知本人,在此提前多谢)。

捋捋思路

撸撸思路

明天以搭建贰个类型的主干框架为例,来商量这一个题材,最终的成效图如下:

图片 1

来得效果

世家可以看来,那的确是3个繁杂项目的基本功,固然逻辑再繁杂的界面,最开首也都是从那么些界面起步的,而对此它,我们须要做的:

  • 初步化多少个子控制器
  • 添加自定义的 TabBarView
  • 添加自定义的 NavigationBar
  • 添加自定的 TopBarColumnView
要促成如何的效率?

图片 2

TogglingReadingMode

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

准备干活

那里关键是准备一些档次花费须求的财富和增进一些须要利用到的第①方库,进度不难、琐碎:

  • 导入需求使用到的方方面面图片能源
  • 导入必要动用到的第①方: 奥迪Q3x斯维夫特、汉兰达xCocoa
  • 组成 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 上一向得到这一步的代码

运用场馆

3个采纳,为满意用户多变的私欲,拥有多少个宗旨风格、分裂的翻阅方式(日间/夜间),那种情景喜人,像某易某音乐,就同时兼有性情换肤和夜间格局的功力

图片 3

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

但尽管二个行使具有再多的品格,本质无非是先期准备好这个差别风格的「颜色样式」、「图片样式」、「遮罩样式」而已,当你点击调整风格的按钮,全数需求替换风格的界面收到公告之后,得到先行准备好的体裁举行替换即可。

正题

截至了富有的预备干活,接下去进入正题:使用 Sportagex斯威夫特 创立 TabBarView
供菜单控制器 MenuViewController 使用

兑现格局

看来,大家须求监听者去监听「方式切换的按钮」,当收到到用户的点击时,布告全数界面,启用另一套主旨风格。因此,我们要求运用到监听方式,由于涉及到多少个界面不一致层次下的监听,我们顺其自然会消除「Delegate」 和 「Block」那二种监听情势,那么在非 Reactive
下,大家也只能选用文告中央那种监听情势了,但实际只要接纳 Reactive
,会简单得专程多,代码品质也会高很多,而且当1个运用具有几十一个界面时,咱们就不须求无止境的去移除监听者,也不必要担心因为有些界面忘了移除监听者而带来的崩溃难题,Reactive
中有1个机关移除监听者的职能,会帮大家处理好那么些事情。

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 唯有三个对外属性,还有三个 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 的采用,由于使用了 CRUISERx斯维夫特,也变得专程不难,也方便管理。
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 的点击操作(那里由于 途乐x斯威夫特 会变得专程简单)
  • 拍卖 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,到此地,大家贰个粗略的种类框架就早已成功,其效劳如下:

图片 4

BasicInterface.gif

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

RxSwift
  • 动用 CocoaPod 将第1方框架 大切诺基xSwift 、牧马人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
的创设是一模一样的,我们都试着去成立体会下。小编那边也不再赘余,而最后的机能如下:

图片 5

Last Version BasicInterface.gif

最终的代码,大家可以在
https://github.com/iJudson/RxBasicInterface
中找到。

假定那么些基本框架还有哪些地点可以继续优化,请不吝评论告知本人。
一旦您认为那个中央框架还不易,欢迎 star。

感谢!

利用 OdysseyxSwift 创设阅读形式(日间/夜间)

我们以创设一个独具三种风格的读书情势为例,而二种风格的拔取皮肤,与此基本是一模一样的,无非是多准备一套风格罢了。

局地再熟识不过的为主配备

正规的话,MVVM 本就为 中华Vx斯维夫特 而生,项目的设计格局最好采纳 MVVM
格局去规划,可是此间的基点是阅读情势的创设,为了节约大家的精通时间,大家可以稍微简单凶恶些

  • 创建 RxReadingMode 项目
  • 在 该项目的 Main.storyBoard
    上充足全体必要添加夜间形式的控件,并连线到代码 ViewController 中
  • 导入 Reactive 框架
    pod ‘RxSwift’, ‘3.6.1’
    pod ‘RxCocoa’, ‘3.6.1’
  • 在 ViewController 中添加头文件
    import RxSwift
    import RxCocoa
    形成以上步骤之后,大家运营下项目,确保这一多级操作下来是未曾其余难题的:

图片 6

开首化状态

Good!没有怎么难题!到此地,我们早就落成了 1/10了。而急需添加夜间形式的控件大家早已准备好了,接下去是还是不是为那一个控件准备不相同情势下的样式呢?

体制管理配置类

我们需求准备两套样式:日间情势和夜间情势。为了方便管理,大家定义样式管理类
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 中读书形式的值,当然大家可以直接得到 1
    中的属性去赋值,可是那样子就将没需求对控制器开放的 Observable
    属性向它开放了,那并不是大家所期望的,那么大家该怎么处理呢?大家经过多个对外的类措施:

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

到这边,落成了此类的安插,但要么总感到少了点什么?这几个类就只有如此点料?大家就那样冷清一个安心乐意的
Variable 属性?

MixedStyle – 混合风格取样类

正如前方所说,咱们创设该类的目标是,向该类输入一些不比的风骨样式,该类就活动输出大家所需求的样式,跟自动售货机一样。听起来很复杂,但是实际很不难。

诶,可是风格类型不是有很各样?大家只怕需求修改图片的背景颜色(UIColor
类型),又或许须求修改 UILabel 的字体大小(CGFloat
类型)。这….?大家那里可以动用泛型类,该类的品类会在输入3个值的时候显然。

而实际,那个类要求做的就唯有一件业务,就是出口二个切实可行的作风样式,然则输入这么三种品格样式,我们到底要出口哪类体制呢?这当然就取决于「上五个操作」被冷落的质量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 控件属性监听者,熟练 SportagexSwift的人可能可以很自由看出,因为 RAV4xSwift 那么些第一方中并从未 UIView
背景颜色监听者,假设大家想有个别 UI
属性成为监听者,我们只好去自定义监听者,KugaxSwift这几个意义显然那多少个好用,详情可知 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

其实,细心的心上人大概发现图片还没添加夜间方式的体制,那几个一连效应大家可以试着落成下,思考怎么样兑现才为「最优」。

企望大家在落到实处的进程中也持有收获…