|
69 | 69 | 2. 由于对 `backgroundColor` 属性进行**不合适的**方法调剂,其行为无法预测
|
70 | 70 | 2. 无法适配第三方 UI 控件
|
71 | 71 |
|
| 72 | +## 使用色表的版本 |
| 73 | + |
| 74 | +为了解决 1.0 中的各种问题,我决定在 2.0 版本中放弃对 `nightBackgroundColor` 的使用,并且重新设计底层的实现,转而使用更为**稳定**、**安全**的方法实现夜间模式,先看一下效果图: |
| 75 | + |
| 76 | +<p align='center'> |
| 77 | + |
72 | 78 | ### DKColorPicker
|
73 | 79 |
|
74 |
| -为了解决 1.0 中的各种问题,我决定在 2.0 版本中放弃对 `nightBackgroundColor` 的使用,并且重新设计底层的实现,转而使用更为**稳定**、**安全**的方法实现夜间模式。 |
| 80 | +与上一个版本实现上的不同,在 2.0 中删除了全部的 `nightBackgroundColor`,使用一个名为 `dk_backgroundColorPicker` 的属性取代它。 |
| 81 | + |
| 82 | +```objectivec |
| 83 | +@property (nonatomic, copy) DKColorPicker dk_backgroundColorPicker; |
| 84 | +``` |
| 85 | + |
| 86 | +这个属性其实就是一个 block,它接收参数 `DKThemeVersion *themeVersion`,但是会返回一个 `UIColor *`: |
| 87 | + |
| 88 | +```objectivec |
| 89 | +typedef UIColor *(^DKColorPicker)(DKThemeVersion *themeVersion); |
| 90 | +``` |
| 91 | + |
| 92 | +比如使用 `DKColorPickerWithRGB` 创建一个临时的 `DKColorPicker`: |
| 93 | + |
| 94 | +1. 在 `DKThemVersionNormal` 时返回 `0xffffff` |
| 95 | +2. 在 `DKThemeVersionNight` 时返回 `0x343434` |
| 96 | +3. 在自定义的主题 `RED` 下返回 `0xfafafa` |
| 97 | + |
| 98 | +```objectivec |
| 99 | +cell.dk_backgroundColorPicker = DKColorPickerWithRGB(0xffffff, 0x343434, 0xfafafa); |
| 100 | +``` |
| 101 | + |
| 102 | +同时,每一个对象还持有一个 `pickers` 数组,来存储自己的全部 `DKColorPicker`: |
| 103 | + |
| 104 | +```objectivec |
| 105 | +@interface NSObject () |
| 106 | + |
| 107 | +@property (nonatomic, strong) NSMutableDictionary<NSString *, DKColorPicker> *pickers; |
| 108 | + |
| 109 | +@end |
| 110 | +``` |
| 111 | + |
| 112 | +在第一次使用这个属性时,会将当前对象注册为 `DKNightVersionThemeChangingNotificaiton` 的通知。 |
| 113 | + |
| 114 | +在每次收到通知时,都会调用 `night_update` 方法,将当前主题传入 `DKColorPicker`,并再次执行。 |
| 115 | + |
| 116 | +```objectivec |
| 117 | +- (void)night_updateColor { |
| 118 | + [self.pickers enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull selector, DKColorPicker _Nonnull picker, BOOL * _Nonnull stop) { |
| 119 | + SEL sel = NSSelectorFromString(selector); |
| 120 | + id result = picker(self.dk_manager.themeVersion); |
| 121 | + [UIView animateWithDuration:DKNightVersionAnimationDuration |
| 122 | + animations:^{ |
| 123 | +#pragma clang diagnostic push |
| 124 | +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" |
| 125 | + [self performSelector:sel withObject:result]; |
| 126 | +#pragma clang diagnostic pop |
| 127 | + }]; |
| 128 | + }]; |
| 129 | +} |
| 130 | +``` |
| 131 | + |
| 132 | +也就是说,在每次改变主题的时候,都会发出通知。 |
| 133 | + |
| 134 | +### DKColorTable |
| 135 | + |
| 136 | +虽然我们在上面临时创建了一些 `DKColorPicker`,不过在 `DKNightVersion` 中,我更推荐使用色表,来减少相同的 `DKColorPicker` 的创建,并且能够更好地管理整个应用中的颜色: |
| 137 | + |
| 138 | +```objectivec |
| 139 | +NORMAL NIGHT RED |
| 140 | +#ffffff #343434 #fafafa BG |
| 141 | +#aaaaaa #313131 #aaaaaa SEP |
| 142 | +#0000ff #ffffff #fa0000 TINT |
| 143 | +#000000 #ffffff #000000 TEXT |
| 144 | +#ffffff #444444 #ffffff BAR |
| 145 | +``` |
| 146 | + |
| 147 | +上面就是默认色表文件 `DKColorTable.txt` 中的内容,其中,第一行表示主题,`NORMAL` 主题必须存在,而且必须为第一行,而最右面的 `BG`、`SEP` 就是对应 `DKColorPicker` 的 key。 |
| 148 | + |
| 149 | +```objectivec |
| 150 | +self.tableView.dk_backgroundColorPicker = DKColorPickerWithKey(BG); |
| 151 | +``` |
| 152 | + |
| 153 | +在使用时,上面的代码就相当于返回了一个在 `NORMAL` 时返回 `#ffffff`、`NIGHT` 时返回 `#343434` 以及 `RED` 时返回 `#fafafa` 的 `DKColorPicker`。 |
| 154 | + |
| 155 | +### pickerify |
| 156 | + |
| 157 | +虽然说,我们使用色表以及 `DKColorPicker` 解决了 |
75 | 158 |
|
76 | 159 |
|
77 | 160 |
|
78 | 161 |
|
| 162 | +> 关注仓库,及时获得更新:[iOS-Source-Code-Analyze](https://github.com/draveness/iOS-Source-Code-Analyze) |
| 163 | +> Follow: [Draveness · Github](https://github.com/Draveness) |
79 | 164 |
|
80 | 165 |
|
0 commit comments