Schedule/README.md

284 lines
6.9 KiB
Markdown
Raw 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([简体中文](README.zh_cn.md))
<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 is a timing tasks scheduler written in Swift. It allows you run timing tasks with elegant and intuitive syntax.
<p align="center">
<img src="assets/demo.png" width="700">
</p>
## Features
- [x] Elegant and intuitive API
- [x] Rich preset rules
- [x] Powerful management mechanism
- [x] Detailed execution history
- [x] Thread safe
- [x] Complete documentation
- [x] ~100%+ test coverage
### Why You Should Use Schedule
| Features | Timer | DispatchSourceTimer | Schedule |
| --- | :---: | :---: | :---: |
| ⏰ Interval-based Schedule | ✓ | ✓ | ✓ |
| 📆 Date-based Schedule | ✓ | | ✓ |
| 🌈 Combined Plan Schedule | | | ✓ |
| 🗣️ Natural Language Parse | | | ✓ |
| 🏷 Batch Task Management | | | ✓ |
| 📝 Execution Record | | | ✓ |
| 🎡 Plan Reset | | ✓ | ✓ |
| 🚦 Suspend, Resume, Cancel | | ✓ | ✓ |
| 🍰 Child-action | | | ✓ |
## Usage
### Overview
Scheduling a task has never been so elegant and intuitive, all you have to do is:
```swift
// 1. define your plan
let plan = Plan.after(3.seconds)
// 2. do your task
let task = plan.do {
print("3 seconds passed!")
}
```
### Rules
#### Interval-based Schedule
The running mechanism of Schedule is based on `Plan`, and `Plan` is actually a sequence of `Interval`.
Schedule makes `Plan` definitions more elegant and intuitive by extending `Int` and `Double`. Also, because `Interval` is a built-in type of Schedule, you don't have to worry about it being polluting your namespace.
```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 { }
```
#### Date-based Schedule
Configuring date-based `Plan` is the same, with the expressive Swift syntax, Schedule makes your code look like a fluent conversation.
```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 { }
```
#### Natural Language Parse
In addition, Schedule also supports simple natural language parsing.
```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(.firday).at("9:00 pm").do { }
Period.registerQuantifier("many", for: 100 * 1000)
let t4 = Plan.every("many days").do { }
```
#### Combined Plan Schedule
Schedule provides several basic collection operators, which means you can use them to customize your own powerful plans.
```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)
```
### Management
#### DispatchQueue
When calling `plan.do` to dispatch a timing task, you can use `queue` to specify which `DispatchQueue` the task will be dispatched to when the time is up. This operation does not rely on `RunLoop` like `Timer`, so you can call it on any thread.
```swift
Plan.every(1.second).do(queue: .global()) {
print("On a globle queue")
}
```
#### RunLoop
If `queue` is not specified, Schedule will use `RunLoop` to dispatch the task, at which point the task will execute on the current thread. **Please note**, like `Timer`, which is also based on `RunLoop`, you need to ensure that the current thread has an **available** `RunLoop`. By default, the task will be added to `.common` mode, you can specify another mode when creating the task.
```swift
let task = Plan.every(1.second).do(mode: .default) {
print("on default mode...")
}
```
#### Timeline
You can observe the execution record of the task in real time using the following properties.
```swift
task.creationDate
task.executionHistory
task.firstExecutionDate
task.lastExecutionDate
task.estimatedNextExecutionDate
```
#### TaskCenter & Tag
Tasks are automatically added to `TaskCenter.default` by defaultyou can organize them using tags and task center.
```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.clear()
let myCenter = TaskCenter()
myCenter.add(task0)
```
### SuspendResume, Cancel
You can `suspend`, `resume`, `cancel` a task.
```swift
let task = Plan.every(1.minute).do { }
// will increase task's suspensionCount
task.suspend()
// will decrease task's suspensionCount,
// but don't worry about excessive resumptions, I will handle these for you~
task.resume()
// will clear task's suspensionCount
// a canceled task can't do anything, event if it is set to a new plan.
task.cancel()
```
#### Action
You can add more actions to a task and remove them at any time you want:
```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)
```
## Installation
### CocoaPods
```ruby
# Podfile
use_frameworks!
target 'YOUR_TARGET_NAME' do
pod 'Schedule', '~> 2.0'
end
```
### Carthage
```
github "luoxiu/Schedule" ~> 2.0
```
### Swift Package Manager
```swift
dependencies: [
.package(
url: "https://github.com/luoxiu/Schedule", .upToNextMajor(from: "2.0.0")
)
]
```
## Contributing
Like **Schedule**? Thanks!!!
At the same time, I need your help~
### Finding Bugs
Schedule is just getting started. If you could help the Schedule find or fix potential bugs, I would be grateful!
### New Features
Have some awesome ideas? Feel free to open an issue or submit your pull request directly!
### Documentation improvements.
Improvements to README and documentation are welcome at all times, whether typos or my lame English, 🤣.
## Acknowledgement
Inspired by Dan Bader's [schedule](https://github.com/dbader/schedule)!