@@ -23,7 +23,7 @@ class CachedAssetSchemeHandler: NSObject, WKURLSchemeHandler {
23
23
return nil
24
24
}
25
25
26
- let worker : Worker
26
+ private let worker : Worker
27
27
28
28
init ( library: EditorAssetsLibrary ) {
29
29
self . worker = . init( library: library)
@@ -40,69 +40,102 @@ class CachedAssetSchemeHandler: NSObject, WKURLSchemeHandler {
40
40
await worker. stop ( urlSchemeTask)
41
41
}
42
42
}
43
+ }
43
44
44
- actor Worker {
45
- struct TaskInfo {
46
- var webViewTask : WKURLSchemeTask
47
- var fetchAssetTask : Task < Void , Never >
45
+ private actor Worker {
46
+ struct TaskInfo {
47
+ var webViewTask : WKURLSchemeTask
48
+ var fetchAssetTask : Task < Void , Never >
48
49
49
- func cancel( ) {
50
- fetchAssetTask. cancel ( )
51
- }
52
- }
50
+ func cancel( ) {
51
+ fetchAssetTask. cancel ( )
52
+ }
53
+ }
54
+
55
+ let library : EditorAssetsLibrary
56
+ var tasks : [ ObjectIdentifier : TaskInfo ] = [ : ]
57
+
58
+ init ( library: EditorAssetsLibrary ) {
59
+ self . library = library
60
+ }
53
61
54
- let library : EditorAssetsLibrary
55
- var tasks : [ ObjectIdentifier : TaskInfo ] = [ : ]
62
+ deinit {
63
+ for (_, task) in tasks {
64
+ task. cancel ( )
65
+ }
66
+ }
56
67
57
- init ( library: EditorAssetsLibrary ) {
58
- self . library = library
68
+ func start( _ task: WKURLSchemeTask ) {
69
+ guard let url = task. request. url, let httpURL = CachedAssetSchemeHandler . originalHTTPURL ( from: url) else {
70
+ task. didFailWithError ( URLError ( . badURL) )
71
+ return
59
72
}
60
73
61
- deinit {
62
- for (_, task) in tasks {
63
- task. cancel ( )
74
+ let taskKey = ObjectIdentifier ( task)
75
+
76
+ let fetchAssetTask = Task { [ library, weak self] in
77
+ do {
78
+ let ( response, content) = try await library. cacheAsset ( from: httpURL, webViewURL: url)
79
+
80
+ await self ? . tasks [ taskKey] ? . webViewTask. didReceive ( response)
81
+ await self ? . tasks [ taskKey] ? . webViewTask. didReceive ( content)
82
+
83
+ await self ? . finish ( with: nil , taskKey: taskKey)
84
+ } catch {
85
+ await self ? . finish ( with: error, taskKey: taskKey)
64
86
}
65
87
}
88
+ tasks [ taskKey] = . init( webViewTask: task, fetchAssetTask: fetchAssetTask)
89
+ }
66
90
67
- func start( _ task: WKURLSchemeTask ) {
68
- guard let url = task. request. url, let httpURL = CachedAssetSchemeHandler . originalHTTPURL ( from: url) else {
69
- task. didFailWithError ( URLError ( . badURL) )
70
- return
71
- }
91
+ func stop( _ task: WKURLSchemeTask ) {
92
+ let taskKey = ObjectIdentifier ( task)
93
+ tasks [ taskKey] ? . cancel ( )
94
+ tasks [ taskKey] = nil
95
+ }
96
+
97
+ private func finish( with error: Error ? , taskKey: ObjectIdentifier ) {
98
+ guard let task = tasks [ taskKey] else { return }
72
99
73
- let taskKey = ObjectIdentifier ( task)
100
+ if let error {
101
+ task. webViewTask. didFailWithError ( error)
102
+ } else {
103
+ task. webViewTask. didFinish ( )
104
+ }
105
+ tasks [ taskKey] = nil
106
+ }
107
+ }
108
+
109
+ @available ( iOS 26 . 0 , * )
110
+ extension CachedAssetSchemeHandler : URLSchemeHandler {
111
+ func reply( for request: URLRequest ) -> AsyncThrowingStream < URLSchemeTaskResult , Error > {
112
+ AsyncThrowingStream { [ library = worker. library] continuation in
113
+ let task = Task {
114
+ guard let url = request. url,
115
+ let httpURL = CachedAssetSchemeHandler . originalHTTPURL ( from: url) else {
116
+ continuation. yield ( with: . failure( URLError ( . badURL) ) )
117
+ continuation. finish ( )
118
+ return
119
+ }
74
120
75
- let fetchAssetTask = Task { [ library, weak self] in
76
121
do {
77
122
let ( response, content) = try await library. cacheAsset ( from: httpURL, webViewURL: url)
123
+ try Task . checkCancellation ( )
78
124
79
- await self ? . tasks [ taskKey] ? . webViewTask. didReceive ( response)
80
- await self ? . tasks [ taskKey] ? . webViewTask. didReceive ( content)
81
-
82
- await self ? . finish ( with: nil , taskKey: taskKey)
125
+ continuation. yield ( with: . success( . response( response) ) )
126
+ continuation. yield ( with: . success( . data( content) ) )
83
127
} catch {
84
- await self ? . finish ( with: error, taskKey: taskKey)
128
+ try Task . checkCancellation ( )
129
+ continuation. yield ( with: . failure( error) )
85
130
}
131
+ continuation. finish ( )
86
132
}
87
- tasks [ taskKey] = . init( webViewTask: task, fetchAssetTask: fetchAssetTask)
88
- }
89
-
90
- func stop( _ task: WKURLSchemeTask ) {
91
- let taskKey = ObjectIdentifier ( task)
92
- tasks [ taskKey] ? . cancel ( )
93
- tasks [ taskKey] = nil
94
- }
95
133
96
- private func finish( with error: Error ? , taskKey: ObjectIdentifier ) {
97
- guard let task = tasks [ taskKey] else { return }
98
-
99
- if let error {
100
- task. webViewTask. didFailWithError ( error)
101
- } else {
102
- task. webViewTask. didFinish ( )
134
+ continuation. onTermination = {
135
+ if case . cancelled = $0 {
136
+ task. cancel ( )
137
+ }
103
138
}
104
- tasks [ taskKey] = nil
105
139
}
106
140
}
107
141
}
108
-
0 commit comments