Schedule/README.zh_cn.md

288 lines
6.9 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Schedule
<p align="center">
<a href="https://github.com/luoxiu/Schedule/releases">
<img src="https://img.shields.io/cocoapods/v/Schedule.svg">
</a>
<img src="https://img.shields.io/travis/luoxiu/Schedule.svg">
<img src="https://img.shields.io/codecov/c/github/luoxiu/Schedule.svg">
<img src="https://img.shields.io/badge/support-CocoaPods%20%7C%20Carthage%20%7C%20SwiftPM-brightgreen.svg">
<img src="https://img.shields.io/cocoapods/p/Schedule.svg">
<img src="https://img.shields.io/github/license/luoxiu/Schedule.svg">
</p>
Schedule 是一个用 Swift 编写的定时任务调度器,它能让你用优雅、直观的语法执行定时任务。
<p align="center">
<img src="assets/demo.png" width="700">
</p>
## 功能
- [x] 优雅,直观的 API
- [x] 丰富的预置规则
- [x] 强大的管理机制
- [x] 细致的执行记录
- [x] 线程安全
- [x] 完整的文档
- [x] ~100% 的测试覆盖
### 为什么你该使用 Schedule而不是……
| 功能 | Timer | DispatchSourceTimer | Schedule |
| --- | :---: | :---: | :---: |
| ⏰ 基于时间间隔调度 | ✓ | ✓ | ✓ |
| 📆 基于日期调度 | ✓ | | ✓ |
| 🌈 组合计划调度 | | | ✓ |
| 🗣️ 自然语言解析 | | | ✓ |
| 🏷 批任务管理 | | | ✓ |
| 📝 执行记录 | | | ✓ |
| 🎡 规则重置 | | ✓ | ✓ |
| 🚦 暂停、继续、取消 | | ✓ | ✓ |
| 🍰 子动作 | | | ✓ |
## 用法
### 一瞥
调度一个定时任务从未如此优雅、直观,你只需要:
```swift
// 1. 定义你的计划:
let plan = Plan.after(3.seconds)
// 2. 执行你的任务:
let task = plan.do {
print("3 seconds passed!")
}
```
### 计划
#### 基于时间间隔调度
Schedule 的机制基于 `Plan`,而 `Plan` 的本质是一系列 `Interval`
Schedule 通过扩展 `Int``Double``Plan` 的定义更加优雅、直观。同时,因为 `Interval` 是 Schedule 的内置类型,所以你不用担心这会对你的命名空间产生污染。
```swift
let t1 = Plan.every(1.second).do { }
let t2 = Plan.after(1.hour, repeating: 1.minute).do { }
let t3 = Plan.of(1.second, 2.minutes, 3.hours).do { }
```
#### 基于日期调度
定制基于日期的 `Plan` 同样如此,配合富有表现力的 Swift 语法Schedule 让你的代码看起来就像一场流畅的对话。
```swift
let t1 = Plan.at(date).do { }
let t2 = Plan.every(.monday, .tuesday).at("9:00:00").do { }
let t3 = Plan.every(.september(30)).at(10, 30).do { }
let t4 = Plan.every("one month and ten days").do { }
let t5 = Plan.of(date0, date1, date2).do { }
```
#### 自然语言解析
除此之外Schedule 还支持简单的自然语言解析。
```swift
let t1 = Plan.every("one hour and ten minutes").do { }
let t2 = Plan.every("1 hour, 5 minutes and 10 seconds").do { }
let t3 = Plan.every(.friday).at("9:00 pm").do { }
Period.registerQuantifier("many", for: 100 * 1000)
let t4 = Plan.every("many days").do { }
```
#### 组合计划调度
Schedule 提供了几个基本的集合操作符,这意味着,你可以使用它们自由组合,定制属于你的强大规则。
```swift
/// Concat
let p0 = Plan.at(birthdate)
let p1 = Plan.every(1.year)
let birthday = p0.concat.p1
let t1 = birthday.do {
print("Happy birthday")
}
/// Merge
let p3 = Plan.every(.january(1)).at("8:00")
let p4 = Plan.every(.october(1)).at("9:00 AM")
let holiday = p3.merge(p4)
let t2 = holiday.do {
print("Happy holiday")
}
/// First
let p5 = Plan.after(5.seconds).concat(Schedule.every(1.day))
let p6 = s5.first(10)
/// Until
let p7 = P.every(.monday).at(11, 12)
let p8 = p7.until(date)
```
### 管理
#### DispatchQueue
调用 `plan.do` 来调度定时任务时,你可以使用 `queue` 来指定当时间到时task 会被派发到哪个 `DispatchQueue` 上。这个操作不像 `Timer` 那样依赖 `RunLoop`,所以你可以在任意线程上使用它。
```swift
let task = Plan.every(1.second).do(queue: .global()) {
print("On a globle queue")
}
```
#### RunLoop
如果没有指定 `queue`Schedule 会使用 `RunLoop` 来调度 task这时task 会在当前线程上执行。**要注意**,和同样基于 `RunLoop``Timer` 一样,你需要保证当前线程有一个**可用**的 `RunLoop`。默认情况下, task 会被添加到 `.common` mode 上,你可以在创建 task 时指定其它 mode。
```swift
let task = Plan.every(1.second).do(mode: .default) {
print("on default mode...")
}
```
#### Timeline
你可以使用以下属性实时地观察 task 的执行记录。
```swift
task.creationDate
task.executionHistory
task.firstExecutionDate
task.lastExecutionDate
task.estimatedNextExecutionDate
```
#### TaskCenter 和 Tag
task 默认会被自动添加到 `TaskCenter.default` 上,你可以使用 tag 配合 taskCenter 来组织 tasks
```swift
let plan = Plan.every(1.day)
let task0 = plan.do(queue: myTaskQueue) { }
let task1 = plan.do(queue: myTaskQueue) { }
TaskCenter.default.addTags(["database", "log"], to: task1)
TaskCenter.default.removeTag("log", from: task1)
TaskCenter.default.suspend(byTag: "log")
TaskCenter.default.resume(byTag: "log")
TaskCenter.default.cancel(byTag: "log")
TaskCenter.default.removeAll()
let myCenter = TaskCenter()
myCenter.add(task0)
```
### Suspend、Resume、Cancel
你可以 suspendresumecancel 一个 task。
```swift
let task = Plan.every(1.minute).do { }
// 会增加 task 的暂停计数
task.suspend()
task.suspensions == 1
// 会减少 task 的暂停计数
// 不过不用担心过度减少,我会帮你处理好这些~
task.resume()
task.suspensions == 0
// 会清零 task 的暂停计数
// 被 cancel 的 task 即使重新设置其它调度规则也不会有任何作用了
task.cancel()
```
#### 子动作
你可以添加更多的 action 到 task并在任意时刻移除它们。
```swift
let dailyTask = Plan.every(1.day)
dailyTask.addAction {
print("open eyes")
}
dailyTask.addAction {
print("get up")
}
let key = dailyTask.addAction {
print("take a shower")
}
dailyTask.removeAction(byKey: key)
```
## 安装
### CocoaPods
```ruby
# Podfile
use_frameworks!
target 'YOUR_TARGET_NAME' do
pod 'Schedule', '~> 2.0'
end
```
### Carthage
```
# Cartfile
github "luoxiu/Schedule" ~> 2.0
```
### Swift Package Manager
```swift
dependencies: [
.package(
url: "https://github.com/luoxiu/Schedule", .upToNextMajor(from: "2.0.0")
)
]
```
## 贡献
喜欢 **Schedule** 吗?谢谢!!!
与此同时如果你想参与进来的话,你可以:
### 找 Bugs
Schedule 还是一个非常年轻的项目,如果你能帮 Schedule 找到甚至解决潜在的 bugs 的话,那就太感谢啦!
### 新功能
有一些有趣的想法?尽管在 issue 里分享出来,或者直接提交你的 Pull Request
### 改善文档
任何时候都欢迎对 README 或者文档注释的修改建议,无论是错别字还是纠正我的蹩脚英文,🤣。
## 致谢
项目灵感来自 Dan Bader 的 [schedule](https://github.com/dbader/schedule)