-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathManagedTask.swift
More file actions
117 lines (95 loc) · 3.03 KB
/
Copy pathManagedTask.swift
File metadata and controls
117 lines (95 loc) · 3.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//
// ManagedTask.swift
// CoreDesignSystem
//
// Created by 전성훈 on 7/12/26.
// Copyright © 2026 com.seonghun.gitsearchmicro. All rights reserved.
//
import Foundation
@MainActor
public final class ManagedTask {
private var task: Task<Void, Never>?
private var generation = 0
public init() {}
deinit {
task?.cancel()
}
public var isRunning: Bool { task != nil }
public func replace(
onError: ((Error) -> Void)? = nil,
operation: @escaping @MainActor () async throws -> Void
) {
task?.cancel()
start(onError: onError, opeartion: operation)
}
public func runIfIdle(
onError: ((Error) -> Void)? = nil,
operation: @escaping @MainActor () async throws -> Void
) {
guard task == nil else { return }
start(onError: onError, opeartion: operation)
}
// MARK: - owner 편의성 (호출부의 [weak self] / guard let self 제거)
public func replace<Owner: AnyObject>(
with owner: Owner,
onError: ((Owner, Error) -> Void)? = nil,
operation: @escaping @MainActor (Owner) async throws -> Void
) {
task?.cancel()
start(
onError: onError.map { handler in
{ [weak owner] error in
guard let owner else { return }
handler(owner, error)
}
},
opeartion: { [weak owner] in
guard let owner else { return }
try await operation(owner)
}
)
}
public func runIfIdle<Owner: AnyObject>(
with owner: Owner,
onError: ((Owner, Error) -> Void)? = nil,
operation: @escaping @MainActor (Owner) async throws -> Void
) {
guard task == nil else { return }
start(
onError: onError.map { handler in
{ [weak owner] error in
guard let owner else { return }
handler(owner, error)
}
},
opeartion: { [weak owner] in
guard let owner else { return }
try await operation(owner)
}
)
}
public func cancel() {
task?.cancel()
task = nil
}
private func start(
onError: ((Error) -> Void)?,
opeartion: @escaping @MainActor () async throws -> Void
) {
generation &+= 1
let startedGeneration = generation
task = Task { [weak self] in
do {
try await opeartion()
} catch is CancellationError {
// 취소는 실패가 이나리 중단
} catch {
// 취소된 작업의 늦은 실패도 침묵
if !Task.isCancelled { onError?(error) }
}
if let self, self.generation == startedGeneration {
self.task = nil
}
}
}
}