<commit_before>![SwiftTheme](https://raw.githubusercontent.com/jiecao-fm/SwiftThemeResources/master/Screenshots/logo.png)

<p align="center">
<a href="#前言">前言</a> -
<a href="#示例">示例</a> -
<a href="#安装">安装</a> -
<a href="#参考">参考</a> -
<a href="#常见问题">常见问题</a> -
<a href="#贡献">贡献</a> -
<a href="README.md">English Document</a>
</p>

<p align="center">
<a href="https://developer.apple.com/swift"><img src="https://img.shields.io/badge/language-swift3-f48041.svg?style=flat"></a>
<a href="https://developer.apple.com/ios"><img src="https://img.shields.io/badge/platform-iOS%207%2B-blue.svg?style=flat"></a>
<a href="https://github.com/Carthage/Carthage"><img src="https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat"></a>
<a href="http://cocoadocs.org/docsets/SwiftTheme"><img src="https://img.shields.io/badge/CocoaPods-compatible-4BC51D.svg?style=flat"></a>
<a href="https://github.com/jiecao-fm/SwiftTheme/blob/master/LICENSE"><img src="http://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat"></a>
<a href="https://github.com/jiecao-fm/SwiftTheme/tree/0.3"><img src="https://img.shields.io/badge/release-0.3-blue.svg"></a>
<a href="https://travis-ci.org/jiecao-fm/SwiftTheme"><img src="https://travis-ci.org/jiecao-fm/SwiftTheme.svg"></a>
<a href="https://codebeat.co/projects/github-com-jiecao-fm-swifttheme"><img alt="codebeat badge" src="https://codebeat.co/badges/900eef02-9b88-46eb-8ce9-440c1dc31435" /></a>
</p>

## 截屏

![](https://github.com/jiecao-fm/SwiftThemeResources/blob/master/Screenshots/switch.gif)

> 运行：打开`SwiftTheme.xcworkspace`选择构建目标为`PlistDemo`

## 前言
### 缘起
项目需求，我们要为[节操精选](http://um0.cn/5FpZs)开发夜间模式功能。我们的需求不是简单的调整亮度或者`alpha`，而是更换为一套更深色的UI。因此所谓夜间模式其实就是特定的更换主题（换肤）功能。

如何实现呢？判断某个全局变量，然后在初始化视图控件时设置不同的背景色或者加载不同的切图文件？但是在切换主题时，已经初始化好的视图控件呢？没错，也许你也想到了通过通知让相应的视图控件修改背景色或切图。想到这里你应该也意识到了Controller中将充斥着注册通知、`if...else`、更新视图控件的代码，糟糕的是如果忘记了注销通知还可能引起应用崩溃。

一番思考后，我们对该任务提出了更高的要求，打造一套简单、可复用的主题框架，正如你看到的这样。

### 目标
将`SwiftTheme`打造为一款简单、功能丰富、高性能、可扩展的主题框架（换肤框架），为iOS 平台提供一个统一的主题解决方案。

## 示例

### 索引方式

让 `UIView` 随主题变换背景色：

```swift
view.theme_backgroundColor = ["#FFF", "#000"]
```

让 `UILabel` 和 `UIButton` 随主题变换文字颜色：

```swift
label.theme_textColor = ["#000", "#FFF"]
button.theme_setTitleColor(["#000", "#FFF"], forState: .Normal)
```

让 `UIImageView` 随主题变换切图：

```swift
imageView.theme_image = ["day", "night"]

// 不想通过切图名，想通过 UIImage 来设置不同主题的图片也是可以的
imageView.theme_image = ThemeImagePicker(images: image1, image2)
```

然后，当你执行如下代码时，奇迹发生了！

```swift
// 例如isNight为true，imageView将会使用 "night" 的切图
ThemeManager.setTheme(index: isNight ? 1 : 0)
```

随时获取当前主题的索引：

```swift
ThemeManager.currentThemeIndex	// Readonly
```

> 直接根据索引切换主题，便于快速开发。适合主题不多、无需下载主题的App。

关于字面量需要注意的：

```swif
// 以下的写法是错误的
let colors = ["#FFF", "#000"]
view.theme_backgroundColor = colors

// 应该这样
view.theme_backgroundColor = ["#FFF", "#000"]
// 或者
let colorPickers: ThemeColorPicker = ["#FFF", "#000"]
view.theme_backgroundColor = colorPickers
```

> 因为 theme_backgroundColor 接受的是ThemeColorPicker 类型的参数，而不是Array，而 view.theme_backgroundColor = ["#FFF", "#000"] 其实是它的字面量写法




### plist 方式
为了满足通过网络下载和安装主题包的需求，我们支持以`plist`配置主题。简单讲就是在`plist` 中记录配置参数，比如背景色、切图文件名等，在代码中通过`keyPath`来指定相应的位置。因此，该`plist`文件以及用到的资源文件就组成了一个主题包。

以下为用法示例：

```swift
view.theme_backgroundColor = "Global.backgroundColor"
imageView.theme_image = "SelectedThemeCell.iconImage"
```
> 与索引方式类似，只是具体的参数值变为了`plist`中的`keyPath`，正因如此赋予了它扩展的能力。
<commit_msg>Update Chinese readme about literal<commit_after>![SwiftTheme](https://raw.githubusercontent.com/jiecao-fm/SwiftThemeResources/master/Screenshots/logo.png)

<p align="center">
<a href="#前言">前言</a> -
<a href="#示例">示例</a> -
<a href="#安装">安装</a> -
<a href="#参考">参考</a> -
<a href="#常见问题">常见问题</a> -
<a href="#贡献">贡献</a> -
<a href="README.md">English Document</a>
</p>

<p align="center">
<a href="https://developer.apple.com/swift"><img src="https://img.shields.io/badge/language-swift3-f48041.svg?style=flat"></a>
<a href="https://developer.apple.com/ios"><img src="https://img.shields.io/badge/platform-iOS%207%2B-blue.svg?style=flat"></a>
<a href="https://github.com/Carthage/Carthage"><img src="https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat"></a>
<a href="http://cocoadocs.org/docsets/SwiftTheme"><img src="https://img.shields.io/badge/CocoaPods-compatible-4BC51D.svg?style=flat"></a>
<a href="https://github.com/jiecao-fm/SwiftTheme/blob/master/LICENSE"><img src="http://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat"></a>
<a href="https://github.com/jiecao-fm/SwiftTheme/tree/0.3"><img src="https://img.shields.io/badge/release-0.3-blue.svg"></a>
<a href="https://travis-ci.org/jiecao-fm/SwiftTheme"><img src="https://travis-ci.org/jiecao-fm/SwiftTheme.svg"></a>
<a href="https://codebeat.co/projects/github-com-jiecao-fm-swifttheme"><img alt="codebeat badge" src="https://codebeat.co/badges/900eef02-9b88-46eb-8ce9-440c1dc31435" /></a>
</p>

## 截屏

![](https://github.com/jiecao-fm/SwiftThemeResources/blob/master/Screenshots/switch.gif)

> 运行：打开`SwiftTheme.xcworkspace`选择构建目标为`PlistDemo`

## 前言
### 缘起
项目需求，我们要为[节操精选](http://um0.cn/5FpZs)开发夜间模式功能。我们的需求不是简单的调整亮度或者`alpha`，而是更换为一套更深色的UI。因此所谓夜间模式其实就是特定的更换主题（换肤）功能。

如何实现呢？判断某个全局变量，然后在初始化视图控件时设置不同的背景色或者加载不同的切图文件？但是在切换主题时，已经初始化好的视图控件呢？没错，也许你也想到了通过通知让相应的视图控件修改背景色或切图。想到这里你应该也意识到了Controller中将充斥着注册通知、`if...else`、更新视图控件的代码，糟糕的是如果忘记了注销通知还可能引起应用崩溃。

一番思考后，我们对该任务提出了更高的要求，打造一套简单、可复用的主题框架，正如你看到的这样。

### 目标
将`SwiftTheme`打造为一款简单、功能丰富、高性能、可扩展的主题框架（换肤框架），为iOS 平台提供一个统一的主题解决方案。

## 示例

### 索引方式

让 `UIView` 随主题变换背景色：

```swift
view.theme_backgroundColor = ["#FFF", "#000"]
```

让 `UILabel` 和 `UIButton` 随主题变换文字颜色：

```swift
label.theme_textColor = ["#000", "#FFF"]
button.theme_setTitleColor(["#000", "#FFF"], forState: .Normal)
```

让 `UIImageView` 随主题变换切图：

```swift
imageView.theme_image = ["day", "night"]

// 不想通过切图名，想通过 UIImage 来设置不同主题的图片也是可以的
imageView.theme_image = ThemeImagePicker(images: image1, image2)
```

然后，当你执行如下代码时，奇迹发生了！

```swift
// 例如isNight为true，imageView将会使用 "night" 的切图
ThemeManager.setTheme(index: isNight ? 1 : 0)
```

随时获取当前主题的索引：

```swift
ThemeManager.currentThemeIndex	// Readonly
```

> 直接根据索引切换主题，便于快速开发。适合主题不多、无需下载主题的App。

关于字面量需要注意的：

```swif
// 以下的写法是错误的
let colors = ["#FFF", "#000"]
view.theme_backgroundColor = colors

// 应该这样
view.theme_backgroundColor = ["#FFF", "#000"]
// 或者
let colorPickers: ThemeColorPicker = ["#FFF", "#000"]
view.theme_backgroundColor = colorPickers
```

> 因为 theme_backgroundColor 接受的是ThemeColorPicker 类型的参数，而不是Array，而 view.theme_backgroundColor = ["#FFF", "#000"] 其实是用字面量初始化一个ThemeColorPicker 并赋值给theme_backgroundColor




### plist 方式
为了满足通过网络下载和安装主题包的需求，我们支持以`plist`配置主题。简单讲就是在`plist` 中记录配置参数，比如背景色、切图文件名等，在代码中通过`keyPath`来指定相应的位置。因此，该`plist`文件以及用到的资源文件就组成了一个主题包。

以下为用法示例：

```swift
view.theme_backgroundColor = "Global.backgroundColor"
imageView.theme_image = "SelectedThemeCell.iconImage"
```
> 与索引方式类似，只是具体的参数值变为了`plist`中的`keyPath`，正因如此赋予了它扩展的能力。

{'fraction_non_alphanumeric': 0.19653179190751446, 'fraction_numerical': 0.019653179190751446, 'mean_word_length': 6.882687927107061, 'pattern_counts': {'":': 0, '<': 87, '<?xml version=': 0, '>': 95, 'https://': 32, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1617925', 'n_tokens_mistral': 3843, 'n_tokens_neox': 3923, 'n_words': 305}