Skip to content

Commit 97c91b2

Browse files
authored
Implement the play(_:) method (#4)
* Implement the `play(_:)` method * Implement conformance to the Sendable protocol * Update `CHANGELOG.md`
1 parent 95b2b1f commit 97c91b2

File tree

5 files changed

+147
-2
lines changed

5 files changed

+147
-2
lines changed

CHANGELOG.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,17 @@
22
All notable changes to this project will be documented in this file.
33

44
#### 1.x Releases
5+
- `1.2.x` Releases - [1.2.0](#120)
56
- `1.1.x` Releases - [1.1.0](#110)
67
- `1.0.x` Releases - [1.0.0](#100) | [1.0.1](#101)
78

9+
## [1.2.0](https://github.com/space-code/haptic-feedback/releases/tag/1.2.0)
10+
Released on 2025-01-08.
11+
12+
#### Added
13+
- Implement the `play(_:)` method.
14+
- Added in Pull Request [#4](https://github.com/space-code/haptic-feedback/pull/4).
15+
816
## [1.1.0](https://github.com/space-code/haptic-feedback/releases/tag/1.1.0)
917
Released on 2024-12-25.
1018

@@ -24,4 +32,4 @@ Released on 2023-11-26.
2432

2533
#### Added
2634
- Initial release of `haptic-feedback`.
27-
- Added by [Nikita Vasilev](https://github.com/nik3212).
35+
- Added by [Nikita Vasilev](https://github.com/nik3212).
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// haptic-feedback
3+
// Copyright © 2025 Space Code. All rights reserved.
4+
//
5+
6+
import Foundation
7+
extension OperationQueue {
8+
static var serial: OperationQueue {
9+
let queue = OperationQueue()
10+
queue.maxConcurrentOperationCount = 1
11+
return queue
12+
}
13+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//
2+
// haptic-feedback
3+
// Copyright © 2025 Space Code. All rights reserved.
4+
//
5+
6+
import Foundation
7+
8+
/// An operation that triggers haptic feedback using the provided `HapticFeedback` object.
9+
/// This operation is executed on the main thread to ensure the haptic feedback is played properly.
10+
final class HapticOperation: Operation, @unchecked Sendable {
11+
// MARK: - Properties
12+
13+
/// The `HapticFeedback` instance used to generate the haptic feedback.
14+
private let haptic: HapticFeedback
15+
16+
// MARK: - Initialization
17+
18+
/// Initializes a `HapticOperation` with a specified `HapticFeedback` object.
19+
///
20+
/// - Parameter haptic: The `HapticFeedback` instance that will generate the haptic feedback.
21+
init(haptic: HapticFeedback) {
22+
self.haptic = haptic
23+
}
24+
25+
// MARK: - Operation Execution
26+
27+
/// The main method of the operation where the haptic feedback is triggered.
28+
///
29+
/// This method ensures that the haptic feedback is generated on the main thread.
30+
override func main() {
31+
guard !isCancelled else {
32+
return
33+
}
34+
35+
DispatchQueue.main.sync {
36+
self.haptic.generate()
37+
}
38+
}
39+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//
2+
// haptic-feedback
3+
// Copyright © 2025 Space Code. All rights reserved.
4+
//
5+
6+
import Foundation
7+
8+
/// An operation that introduces a delay for a specified duration.
9+
/// Used to sequence operations in the `HapticFeedback` queue.
10+
final class WaitOperation: Operation, @unchecked Sendable {
11+
// MARK: - Properties
12+
13+
/// The duration of the wait in seconds.
14+
private let duration: TimeInterval
15+
16+
// MARK: - Initialization
17+
18+
/// Initializes a `WaitOperation` with a specified delay duration.
19+
///
20+
/// - Parameter duration: The time interval, in seconds, for which the operation should pause execution.
21+
init(duration: TimeInterval) {
22+
self.duration = duration
23+
}
24+
25+
// MARK: - Operation Execution
26+
27+
/// The main method of the operation where the delay is applied.
28+
///
29+
/// This method blocks the current thread for the specified duration.
30+
override func main() {
31+
guard !isCancelled else {
32+
return
33+
}
34+
35+
Thread.sleep(forTimeInterval: duration)
36+
print("SLEEP")
37+
}
38+
}

Sources/HapticFeedback/Classes/HapticFeedback.swift

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
//
22
// haptic-feedback
3-
// Copyright © 2024 Space Code. All rights reserved.
3+
// Copyright © 2025 Space Code. All rights reserved.
44
//
55

66
import UIKit
77

8+
// MARK: - HapticFeedback
9+
810
/// Enum defining different types of haptic feedback
911
@MainActor
1012
public enum HapticFeedback: Equatable {
@@ -35,3 +37,48 @@ public enum HapticFeedback: Equatable {
3537
}
3638
}
3739
}
40+
41+
extension HapticFeedback {
42+
/// A private serial operation queue to ensure haptic feedback operations are executed sequentially.
43+
private static let queue: OperationQueue = .serial
44+
45+
/// Plays a sequence of haptic feedback notes.
46+
///
47+
/// - Parameter notes: An array of `Note` objects, each representing either a haptic feedback or a delay.
48+
public static func play(_ notes: [Note]) {
49+
guard queue.operations.isEmpty else {
50+
return
51+
}
52+
53+
for note in notes {
54+
let operation = note.operation
55+
56+
if let last = queue.operations.last {
57+
operation.addDependency(last)
58+
}
59+
60+
queue.addOperation(operation)
61+
}
62+
}
63+
}
64+
65+
// MARK: HapticFeedback.Note
66+
67+
public extension HapticFeedback {
68+
enum Note {
69+
/// A haptic feedback event.
70+
case haptic(HapticFeedback)
71+
/// A delay before the next event.
72+
case wait(TimeInterval)
73+
74+
/// Converts the note into an `Operation` for execution in the serial queue.
75+
var operation: Operation {
76+
switch self {
77+
case let .haptic(haptic):
78+
return HapticOperation(haptic: haptic)
79+
case let .wait(duration):
80+
return WaitOperation(duration: duration)
81+
}
82+
}
83+
}
84+
}

0 commit comments

Comments
 (0)