![]() |
||
---|---|---|
Schedule.playground | ||
Schedule.xcodeproj | ||
Sources/Schedule | ||
Tests | ||
.codecov.yml | ||
.gitignore | ||
.swift-version | ||
.swiftlint.yml | ||
.travis.yml | ||
LICENSE | ||
Package.swift | ||
README.md | ||
README.zh_cn.md | ||
Schedule.podspec | ||
demo.png | ||
logo.png |
README.md
Schedule(简体中文)
⏳ Schedule is a lightweight task scheduler for Swift. It allows you run timed tasks using an incredibly human-friendly syntax.
Features
- Variety of Scheduling Rules
- Suspend, Resume, Cancel
- Reschedule
- Tag-based Task Management
- Child-action Add/Remove
- Natural Language Parse
- Thread Safe
- Full Control Over the Life Cycle
- 95%+ Test Coverage
- Extensive Documention(All Public Types & Methods)
- Linux Support(Tested on Ubuntu 16.04)
- Incredibly Human-friendly APIs
Why You Should Use Schedule
A chart is worth a thousand words:
Features | Timer | DispatchSourceTimer | Schedule |
---|---|---|---|
⏰ Interval-based Schedule | ✓ | ✓ | ✓ |
📆 Date-based Schedule | ✓ | ✓ | |
🌈 Mixing Rules Schedule | ✓ | ||
🚦 Suspend, Resume, Cancel | ✓ | ✓ | |
🎡 Reschedule | ✓ | ✓ | |
🏷 Tag-based Task Management | ✓ | ||
🍰 Child-action Add/Remove | ✓ | ||
📝 Natural Language Parse | ✓ | ||
🚔 Atomic Operation | ✓ | ||
🚀 Realtime Timeline Inspect | ✓ | ||
🎯 Lifetime Specify | ✓ | ||
🍭 Incredibly Human Friendly APIs | ✓ |
Usage
Scheduling a task has never been so simple and intuitive:
Schedule.after(3.seconds).do {
print("3 seconds passed!")
}
Schedule
Interval-based Schedule
Schedule uses a built-in type Interval
to configure timed tasks, so there is no pollution of the namespace. The elegant constructors make the entire configuration work like an easy conversation with an old firend:
Schedule.every(1.second).do { }
Schedule.after(1.hour, repeating: 1.minute).do { }
Schedule.of(1.second, 2.minutes, 3.hours).do { }
Date-based Schedule
Configuring date-based timing tasks is the same:
Schedule.at(when).do { }
Schedule.every(.monday, .tuesday).at("9:00:00").do { }
Schedule.every(.september(30)).at(10, 30).do { }
Schedule.every("one month and ten days").do { }
Schedule.of(date0, date1, date2).do { }
Natural Language Parse
And, Schedule supports basic natural language parsing, which greatly improves the readability of your code:
Schedule.every("one hour and ten minutes").do { }
Schedule.every("1 hour, 5 minutes and 10 seconds").do { }
Schedule.every(.friday).at("9:00 pm").do { }
// Extensions
Period.registerQuantifier("many", for: 100 * 1000)
let period = Period("many days")
Mixing Rules Schedule
Schedule provides several collection operators, this means you can use them to customize your awesome rules:
/// Concat
let s0 = Schedule.at(birthdate)
let s1 = Schedule.every(1.year)
let birthdaySchedule = s0.concat.s1
birthdaySchedule.do {
print("Happy birthday")
}
/// Merge
let s3 = Schedule.every(.january(1)).at("8:00")
let s4 = Schedule.every(.october(1)).at("9:00 AM")
let holiday = s3.merge(s4)
holidaySchedule.do {
print("Happy holiday")
}
/// First
let s5 = Schedule.after(5.seconds).concat(Schedule.every(1.day))
let s6 = s5.first(10)
/// Until
let s7 = Schedule.every(.monday).at(11, 12)
let s8 = s7.until(date)
Management
In schedule, every newly created task is automatically held by an internal global variable and will not be released until you cancel it actively. So you don't have to add variables to your controller and write nonsense like weak var timer: Timer
, self.timer = timer
:
let task = Schedule.every(1.minute).do { }
// will increase task's suspensions
task.suspend()
// will decrease task's suspensions,
// but don't worry about excessive resumptions, I will handle these for you~
task.resume()
// cancel task, this will remove task from the internal holder,
// in other words, will reduce task's reference count,
// if there are no other holders, task will be released.
task.cancel()
Parasitism
Schedule provides a parasitic mechanism, that allows you to handle one of the most common scenarios in a more elegant way:
Schedule.every(1.second).do(host: self) {
// do something, and cancel the task when host is deallocated.
// this's very useful when you want to bind a task's lifetime to a controller.
}
Action
You can add more actions to a task and delete them at any time you want:
let dailyTask = Schedule.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)
Tag
You can organize tasks with tags, and use queue to specify to where the task should be dispatched:
let s = Schedule.every(1.day)
let task0 = s.do(queue: myTaskQueue, tag: "log") { }
let task1 = s.do(queue: myTaskQueue, tag: "log") { }
task0.addTag("database")
task1.removeTag("log")
Task.suspend(byTag: "log")
Task.resume(byTag: "log")
Task.cancel(byTag: "log")
Timeline
You can inspect the timeline of a task in real time:
let timeline = task.timeline
print(timeline.firstExecution)
print(timeline.lastExecution)
print(timeline.estimatedNextExecution)
Lifetime
And specify the lifetime of task:
// will be cancelled after 10 hours.
task.setLifetime(10.hours)
// will add 1 hour to tasks lifetime
task.addLifetime(1.hour)
task.restOfLifetime == 11.hours
Requirements
- Swift 4.x
- iOS 8.0+ / macOS 10.10+ / tvOS 9.0+ / watchOS 2.0+
- Linux(Tested on Ubuntu 16.04)
Installation
CocoaPods
# Podfile
use_frameworks!
target 'YOUR_TARGET_NAME' do
pod 'Schedule', '~> 0.1'
end
Carthage
github "jianstm/Schedule"
Swift Package Manager
dependencies: [
.package(url: "https://github.com/jianstm/Schedule", .upToNextMajor(from: "0.1.0"))
]
Acknowledgement
The design of APIs is inspired by Dan Bader's python package schedule and ruby's slick Syntax!
Contributing
Like Schedule? Thank you so much! At the same time, I need your help:
Finding Bugs
Schedule is just getting started. Although I had tried to write a lot of test cases(over 95%), it is still difficult to say how far the project is from bug free. If you could help the Schedule find or even fix bugs that haven't been discovered yet, I would appreciate it!
New Features
Any 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. For users, the documentation is sometimes much more important than the specific code implementation.
Share
The more users the project has, the more robust the project will become, so, star! fork! and tell your friends!