@@ -15,7 +15,7 @@ protocol ConversionsProvider: AnyObject {
15
15
func getConversions( _ completion: @escaping ( [ String ] ) -> ( ) )
16
16
}
17
17
typealias DataBuilderCompletion = ( _ res: Encodable ) -> Void
18
- typealias DataBuilder = ( _ completion: @escaping DataBuilderCompletion ) -> Encodable ?
18
+ typealias DataBuilder = ( _ completion: @escaping DataBuilderCompletion ) -> Void
19
19
20
20
class TikOperation : Operation , @unchecked Sendable {
21
21
private let dataBuilder : DataBuilder
@@ -24,6 +24,9 @@ class TikOperation: Operation, @unchecked Sendable {
24
24
private let path : String
25
25
private let contentType : ContentType
26
26
27
+ private var timer : DispatchSourceTimer ?
28
+ private let lock = NSRecursiveLock ( )
29
+
27
30
init (
28
31
dataBuilder: @escaping DataBuilder ,
29
32
dispatchDate: Date ,
@@ -39,31 +42,47 @@ class TikOperation: Operation, @unchecked Sendable {
39
42
super. init ( )
40
43
}
41
44
42
- private var timer : DispatchSourceTimer ?
43
-
44
- private var running : Bool = false {
45
- didSet {
46
- willChangeValue ( forKey: " isFinished " )
47
- willChangeValue ( forKey: " isExecuting " )
48
- didChangeValue ( forKey: " isFinished " )
49
- didChangeValue ( forKey: " isExecuting " )
45
+ private var _running : Bool = false
46
+ private var running : Bool {
47
+ get {
48
+ lock. lock ( )
49
+ defer { lock. unlock ( ) }
50
+ return _running
51
+ }
52
+ set {
53
+ var didChange = false
54
+ lock. lock ( )
55
+ if _running != newValue {
56
+ willChangeValue ( forKey: " isFinished " )
57
+ willChangeValue ( forKey: " isExecuting " )
58
+ _running = newValue
59
+ didChange = true
60
+ }
61
+ lock. unlock ( )
62
+
63
+ if didChange {
64
+ didChangeValue ( forKey: " isFinished " )
65
+ didChangeValue ( forKey: " isExecuting " )
66
+ }
50
67
}
51
68
}
52
-
69
+
53
70
override var isAsynchronous : Bool { true }
54
-
55
71
override var isFinished : Bool { !running }
56
-
57
72
override var isExecuting : Bool { running }
58
73
59
74
override func start( ) {
60
- guard !isCancelled else { return }
75
+ guard !isCancelled else {
76
+ finish ( )
77
+ return
78
+ }
79
+
61
80
running = true
62
81
63
82
let timer = DispatchSource . makeTimerSource ( queue: DispatchQueue . global ( qos: . utility) )
64
83
let timeInterval = dispatchDate. timeIntervalSinceNow
65
- let deadline = DispatchTime . now ( ) + timeInterval
66
-
84
+ let deadline = DispatchTime . now ( ) + max ( timeInterval, 0 )
85
+
67
86
timer. schedule ( deadline: deadline)
68
87
69
88
timer. setEventHandler { [ weak self] in
@@ -86,23 +105,25 @@ class TikOperation: Operation, @unchecked Sendable {
86
105
self . finish ( )
87
106
}
88
107
89
- let data = self . dataBuilder ( track)
90
-
91
- if data != nil {
92
- track ( data)
93
- }
108
+ self . dataBuilder ( track)
94
109
}
95
110
96
111
self . timer = timer
97
112
timer. resume ( )
98
113
}
99
114
100
115
override func cancel( ) {
101
- finish ( )
102
116
super. cancel ( )
117
+ finish ( )
103
118
}
104
119
105
120
private func finish( ) {
121
+ lock. lock ( )
122
+ defer { lock. unlock ( ) }
123
+
124
+ guard running else { return }
125
+
126
+ timer? . setEventHandler { }
106
127
timer? . cancel ( )
107
128
timer = nil
108
129
running = false
0 commit comments