|
1 | | -# AsyncTimer |
| 1 | +# AsyncTimer |
| 2 | + |
| 3 | +[](https://swift.org) |
| 4 | +[](https://developer.apple.com) |
| 5 | +[](https://swift.org/package-manager) |
| 6 | +[](https://opensource.org/licenses/MIT) |
| 7 | + |
| 8 | +A lightweight, modern Swift async/await timer implementation for Apple platforms. AsyncTimer provides a clean, actor-based API for scheduling one-time and repeating tasks with precise control over timing, priorities, and cancellation. |
| 9 | + |
| 10 | +## Features |
| 11 | + |
| 12 | +- ✅ **Swift Concurrency** - Built with Swift's modern concurrency model using async/await and actors |
| 13 | +- ✅ **Flexible Timing** - Support for one-time and repeating timers with configurable intervals |
| 14 | +- ✅ **Task Priorities** - Set execution priorities for your timer tasks |
| 15 | +- ✅ **Immediate Firing Option** - Configure timers to fire immediately or after the first interval |
| 16 | +- ✅ **Cancellation Support** - Clean cancellation with optional cancellation handlers |
| 17 | +- ✅ **Dynamic Interval Adjustment** - Change timer intervals on-the-fly |
| 18 | +- ✅ **Thread Safety** - Actor-based design ensures thread-safe operation |
| 19 | +- ✅ **Lightweight** - Zero dependencies, minimal footprint |
| 20 | + |
| 21 | +## Requirements |
| 22 | + |
| 23 | +- Swift 5.9+ / Swift 6.0 |
| 24 | +- iOS 13.0+ |
| 25 | +- macOS 10.15+ |
| 26 | +- tvOS 13.0+ |
| 27 | +- watchOS 6.0+ |
| 28 | +- visionOS 1.0+ |
| 29 | + |
| 30 | +## Installation |
| 31 | + |
| 32 | +### Swift Package Manager |
| 33 | + |
| 34 | +Add AsyncTimer to your project using Swift Package Manager by adding it to your `Package.swift` file's dependencies: |
| 35 | + |
| 36 | +```swift |
| 37 | +dependencies: [ |
| 38 | + .package(url: "https://github.com/yourusername/AsyncTimer.git", from: "0.0.1") |
| 39 | +] |
| 40 | +``` |
| 41 | + |
| 42 | +Or add it directly in Xcode: |
| 43 | +1. Go to **File** > **Add Packages...** |
| 44 | +2. Enter the repository URL: `https://github.com/yourusername/AsyncTimer.git` |
| 45 | +3. Select the version or branch you want to use |
| 46 | + |
| 47 | +## Usage |
| 48 | + |
| 49 | +### Basic Examples |
| 50 | + |
| 51 | +#### One-time Timer |
| 52 | + |
| 53 | +```swift |
| 54 | +import AsyncTimer |
| 55 | + |
| 56 | +func example() async { |
| 57 | + let timer = AsyncTimer( |
| 58 | + interval: 1.0, // 1 second |
| 59 | + repeating: false, |
| 60 | + handler: { |
| 61 | + print("Timer fired once!") |
| 62 | + } |
| 63 | + ) |
| 64 | + |
| 65 | + await timer.start() |
| 66 | + // Timer will fire after 1 second and then stop automatically |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +#### Repeating Timer |
| 71 | + |
| 72 | +```swift |
| 73 | +import AsyncTimer |
| 74 | + |
| 75 | +func example() async { |
| 76 | + let timer = AsyncTimer( |
| 77 | + interval: 0.5, // 0.5 seconds |
| 78 | + repeating: true, |
| 79 | + handler: { |
| 80 | + print("Timer fired repeatedly!") |
| 81 | + } |
| 82 | + ) |
| 83 | + |
| 84 | + await timer.start() |
| 85 | + |
| 86 | + // Let the timer run for 3 seconds |
| 87 | + try? await Task.sleep(for: .seconds(3)) |
| 88 | + |
| 89 | + // Stop the timer |
| 90 | + await timer.stop() |
| 91 | +} |
| 92 | +``` |
| 93 | + |
| 94 | +#### Using Cancellation Handler |
| 95 | + |
| 96 | +```swift |
| 97 | +import AsyncTimer |
| 98 | + |
| 99 | +func example() async { |
| 100 | + let timer = AsyncTimer( |
| 101 | + interval: 1.0, |
| 102 | + repeating: true, |
| 103 | + handler: { |
| 104 | + print("Timer fired!") |
| 105 | + }, |
| 106 | + cancelHandler: { |
| 107 | + print("Timer was cancelled!") |
| 108 | + } |
| 109 | + ) |
| 110 | + |
| 111 | + await timer.start() |
| 112 | + |
| 113 | + // Later, when you want to stop the timer |
| 114 | + await timer.stop() // This will trigger the cancelHandler |
| 115 | +} |
| 116 | +``` |
| 117 | + |
| 118 | +#### Changing Timer Interval |
| 119 | + |
| 120 | +```swift |
| 121 | +import AsyncTimer |
| 122 | + |
| 123 | +func example() async { |
| 124 | + let timer = AsyncTimer( |
| 125 | + interval: 1.0, |
| 126 | + repeating: true, |
| 127 | + handler: { |
| 128 | + print("Timer fired!") |
| 129 | + } |
| 130 | + ) |
| 131 | + |
| 132 | + await timer.start() |
| 133 | + |
| 134 | + // Run at 1-second intervals for a while |
| 135 | + try? await Task.sleep(for: .seconds(3)) |
| 136 | + |
| 137 | + // Change to 0.5-second intervals |
| 138 | + await timer.setInterval(0.5) |
| 139 | + |
| 140 | + // Run at new interval for a while |
| 141 | + try? await Task.sleep(for: .seconds(3)) |
| 142 | + |
| 143 | + // Stop the timer |
| 144 | + await timer.stop() |
| 145 | +} |
| 146 | +``` |
| 147 | + |
| 148 | +#### Setting Task Priority |
| 149 | + |
| 150 | +```swift |
| 151 | +import AsyncTimer |
| 152 | + |
| 153 | +func example() async { |
| 154 | + let highPriorityTimer = AsyncTimer( |
| 155 | + interval: 1.0, |
| 156 | + priority: .high, |
| 157 | + repeating: true, |
| 158 | + handler: { |
| 159 | + print("High priority timer fired!") |
| 160 | + } |
| 161 | + ) |
| 162 | + |
| 163 | + let lowPriorityTimer = AsyncTimer( |
| 164 | + interval: 1.0, |
| 165 | + priority: .low, |
| 166 | + repeating: true, |
| 167 | + handler: { |
| 168 | + print("Low priority timer fired!") |
| 169 | + } |
| 170 | + ) |
| 171 | + |
| 172 | + await highPriorityTimer.start() |
| 173 | + await lowPriorityTimer.start() |
| 174 | + |
| 175 | + // High priority timer will generally execute before low priority timer |
| 176 | +} |
| 177 | +``` |
| 178 | + |
| 179 | +## API Reference |
| 180 | + |
| 181 | +### AsyncTimer |
| 182 | + |
| 183 | +```swift |
| 184 | +public final actor AsyncTimer |
| 185 | +``` |
| 186 | + |
| 187 | +A simple repeating timer that runs a task at a specified interval. |
| 188 | + |
| 189 | +#### Initialization |
| 190 | + |
| 191 | +```swift |
| 192 | +public init( |
| 193 | + interval: TimeInterval, |
| 194 | + priority: TaskPriority = .medium, |
| 195 | + repeating: Bool = false, |
| 196 | + firesImmediately: Bool = true, |
| 197 | + handler: @escaping RepeatHandler, |
| 198 | + cancelHandler: CancelHandler? = nil |
| 199 | +) |
| 200 | +``` |
| 201 | + |
| 202 | +- **interval**: The interval at which the timer fires (in seconds) |
| 203 | +- **priority**: The priority of the task (default: `.medium`) |
| 204 | +- **repeating**: Whether the timer should repeat (default: `false`) |
| 205 | +- **firesImmediately**: Whether the timer should fire immediately upon starting (default: `true`, only effective when `repeating` is `true`) |
| 206 | +- **handler**: The handler that is called when the timer fires |
| 207 | +- **cancelHandler**: The handler that is called when the timer is cancelled (optional) |
| 208 | + |
| 209 | +#### Properties |
| 210 | + |
| 211 | +```swift |
| 212 | +public var isRunning: Bool |
| 213 | +``` |
| 214 | + |
| 215 | +Whether the timer is currently running. |
| 216 | + |
| 217 | +#### Methods |
| 218 | + |
| 219 | +```swift |
| 220 | +public func start() |
| 221 | +``` |
| 222 | + |
| 223 | +Starts the timer. If the timer is already running, it will be stopped and restarted. |
| 224 | + |
| 225 | +```swift |
| 226 | +public func stop() |
| 227 | +``` |
| 228 | + |
| 229 | +Stops the timer. |
| 230 | + |
| 231 | +```swift |
| 232 | +public func restart() |
| 233 | +``` |
| 234 | + |
| 235 | +Restarts the timer (equivalent to calling `stop()` followed by `start()`). |
| 236 | + |
| 237 | +```swift |
| 238 | +public func setInterval(_ newInterval: TimeInterval) |
| 239 | +``` |
| 240 | + |
| 241 | +Modifies the interval of the timer. This will also restart the timer if it's currently running. |
| 242 | + |
| 243 | +```swift |
| 244 | +public static func sleep(_ interval: TimeInterval) async throws |
| 245 | +``` |
| 246 | + |
| 247 | +Utility method to sleep for the specified interval. |
| 248 | + |
| 249 | +## Advanced Usage |
| 250 | + |
| 251 | +### Handling Concurrency |
| 252 | + |
| 253 | +Since `AsyncTimer` is implemented as an actor, all its methods are automatically thread-safe. You can safely call methods from different tasks without worrying about race conditions. |
| 254 | + |
| 255 | +```swift |
| 256 | +let timer = AsyncTimer(interval: 1.0, repeating: true) { |
| 257 | + print("Timer fired!") |
| 258 | +} |
| 259 | + |
| 260 | +// These can be called from different tasks safely |
| 261 | +Task { |
| 262 | + await timer.start() |
| 263 | +} |
| 264 | + |
| 265 | +Task { |
| 266 | + try await Task.sleep(for: .seconds(5)) |
| 267 | + await timer.stop() |
| 268 | +} |
| 269 | +``` |
| 270 | + |
| 271 | +## Contributing |
| 272 | + |
| 273 | +Contributions are welcome! If you find a bug or have a feature request, please open an issue. If you'd like to contribute code, please fork the repository and submit a pull request. |
| 274 | + |
| 275 | +## License |
| 276 | + |
| 277 | +AsyncTimer is available under the MIT license. See the LICENSE file for more info. |
0 commit comments