質問編集履歴

1

省略されていたコードを追記しまいした

2021/05/09 14:09

投稿

thirdesr34
thirdesr34

スコア36

test CHANGED
File without changes
test CHANGED
@@ -28,83 +28,247 @@
28
28
 
29
29
  ```Swift
30
30
 
31
- /*よくあるシングルトンのサンプルの抜粋*/
31
+ /*URLSessionとURLSessionDelegateをまとめたクラスのサンプル*/
32
+
32
-
33
+ import Foundation
34
+
33
- class NetworkDownloaderSingleton: NSObject, URLSessionDownloadDelegate, URLSessionDelegate {
35
+ class NetworkDownloader: NSObject {
34
-
36
+
35
- static let shared = NetworkDownloaderSingleton()
37
+ static let shared = NetworkDownloader()
36
38
 
37
39
  var sessionConfiguration = URLSessionConfiguration.default
38
40
 
39
41
  var urlSession: URLSession?
40
42
 
43
+ var runningURLs: [URL: Int] = [:]
44
+
45
+ var runningTasks: [URL: URLSessionDownloadTask] = [:]
46
+
47
+ weak var delegate: NetworkQueueDelegate?
48
+
41
49
  override init() {
42
50
 
43
51
  super.init()
44
52
 
53
+ sessionConfiguration.httpMaximumConnectionsPerHost = 5
54
+
45
- urlSession = URLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: nil)
55
+ urlSession = URLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: .main)
46
-
56
+
47
- }
57
+ }
48
-
58
+
59
+
60
+
49
- func startDownloadTask(with url:URL) {
61
+ func startDownloadTask(with url: String, with opIndex: Int) {
62
+
63
+ print("Starting task: (url)")
64
+
65
+ guard let networkURL = URL(string: url) else {
66
+
67
+ return
68
+
69
+ }
70
+
71
+ runningURLs[networkURL] = opIndex
50
72
 
51
73
  let downloadTask = urlSession?.downloadTask(with: networkURL)
52
74
 
53
- downloadTask.resume()
54
-
55
- }
56
-
57
- }
58
-
59
- //...(URLSessionとNetworkDownloaderSingletonのデリゲート実装部分は省略します)
60
-
61
-
62
-
63
- //利用する場合
64
-
65
- NetworkDownloaderSingleton.shared.delegate = self
66
-
67
- NetworkDownloaderSingleton.shared.startDownloadTask(with: url)
68
-
69
-
70
-
71
-
72
-
73
- /*シングルトンではない場合は以下のようになると思います*/
74
-
75
- class NetworkDownloader: NSObject, URLSessionDownloadDelegate, URLSessionDelegate {
76
-
77
- var sessionConfiguration = URLSessionConfiguration.default
78
-
79
- var urlSession: URLSession?
80
-
81
- override init() {
82
-
83
- super.init()
84
-
85
- urlSession = URLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: nil)
86
-
87
- }
88
-
89
- func startDownloadTask(with url:URL) {
90
-
91
- let downloadTask = urlSession?.downloadTask(with: networkURL)
92
-
93
- downloadTask.resume()
94
-
95
- }
96
-
97
- //...(URLSessionとNetworkDownloaderのデリゲート実装部分は省略します)
98
-
99
-
100
-
101
- //利用する場合
102
-
103
- let downloader = NetworkDownloader()
104
-
105
- downloader.delegate = self
106
-
107
- downloader.startDownloadTask(with: url)
75
+ runningTasks[networkURL] = downloadTask
76
+
77
+ downloadTask?.resume()
78
+
79
+ }
80
+
81
+
82
+
83
+ func cancelDownloadTask(with url: String, with opIndex: Int) {
84
+
85
+ guard let networkURL = URL(string: url) else {
86
+
87
+ return
88
+
89
+ }
90
+
91
+ let task = runningTasks[networkURL]
92
+
93
+ runningTasks.removeValue(forKey: networkURL)
94
+
95
+ runningURLs.removeValue(forKey: networkURL)
96
+
97
+ task?.cancel()
98
+
99
+ }
100
+
101
+
102
+
103
+ }
104
+
105
+
106
+
107
+ extension NetworkDownloader: URLSessionDownloadDelegate, URLSessionDelegate {
108
+
109
+ func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
110
+
111
+ guard let networkURL = downloadTask.currentRequest?.url,
112
+
113
+ let index = runningURLs[networkURL] else {
114
+
115
+ return
116
+
117
+ }
118
+
119
+ // Remove the running task
120
+
121
+ runningTasks.removeValue(forKey: networkURL)
122
+
123
+ runningURLs.removeValue(forKey: networkURL)
124
+
125
+ self.delegate?.notifyOfNetworkOperationCompletion(with: networkURL.absoluteString,
126
+
127
+ fileURL: location.absoluteString,
128
+
129
+ operationIndex: index, error: nil)
130
+
131
+ }
132
+
133
+ func urlSession(_ session: URLSession,
134
+
135
+ downloadTask: URLSessionDownloadTask,
136
+
137
+ didWriteData bytesWritten: Int64,
138
+
139
+ totalBytesWritten: Int64,
140
+
141
+ totalBytesExpectedToWrite: Int64) {
142
+
143
+ guard let networkURL = downloadTask.currentRequest?.url,
144
+
145
+ let index = runningURLs[networkURL] else {
146
+
147
+ return
148
+
149
+ }
150
+
151
+
152
+
153
+ self.delegate?.notifyOfNetworkProgress(progress: "Bytes written: (totalBytesWritten) out of: (totalBytesExpectedToWrite)",
154
+
155
+ operationIndex: index)
156
+
157
+ }
158
+
159
+ func urlSession(_ session: URLSession,
160
+
161
+ task: URLSessionTask,
162
+
163
+ didCompleteWithError error: Error?) {
164
+
165
+ guard let networkURL = task.currentRequest?.url,
166
+
167
+ let index = runningURLs[networkURL] else {
168
+
169
+ return
170
+
171
+ }
172
+
173
+ // Remove the running task
174
+
175
+ runningTasks.removeValue(forKey: networkURL)
176
+
177
+ runningURLs.removeValue(forKey: networkURL)
178
+
179
+ self.delegate?.notifyOfNetworkOperationCompletion(with: networkURL.absoluteString,
180
+
181
+ fileURL: nil,
182
+
183
+ operation Index: index, error: error)
184
+
185
+ }
186
+
187
+ }
188
+
189
+
190
+
191
+ /*利用する場合*/
192
+
193
+ class ViewController: UIViewController {
194
+
195
+ @IBOutlet weak var testQueue: UIButton!
196
+
197
+ override func viewDidLoad() {
198
+
199
+ super.viewDidLoad()
200
+
201
+ // Do any additional setup after loading the view.
202
+
203
+ }
204
+
205
+ @IBAction func testOperationQueue() {
206
+
207
+ let urls = [
208
+
209
+ "https:///xxxx/Test/1.jpg",
210
+
211
+ "https:///xxxx/Test/2.jpg",
212
+
213
+ "https:///xxxx/Test/3.jpg",
214
+
215
+ "https:///xxxx/Test/4.jpg",
216
+
217
+ "https:///xxxx/Test/5.jpg",
218
+
219
+ "https:///xxxx/Test/6.jpg",
220
+
221
+ "https:///xxxx/Test/7.jpg",
222
+
223
+ "https:///xxxx/Test/8.jpg",
224
+
225
+ "https:///xxxx/Test/9.jpg",
226
+
227
+ ]
228
+
229
+
230
+
231
+ NetworkDownloader.shared.delegate = self
232
+
233
+ var index = 1
234
+
235
+ for url in urls {
236
+
237
+ let nonCachedURL = "(url)"
238
+
239
+ NetworkDownloader.shared.startDownloadTask(with: nonCachedURL, with: index)
240
+
241
+ index += 1
242
+
243
+ }
244
+
245
+ }
246
+
247
+ }
248
+
249
+ extension ViewController: NetworkQueueDelegate {
250
+
251
+ func notifyOfNetworkOperationCompletion(with url: String, fileURL: String?, operationIndex: Int, error: Error?) {
252
+
253
+ guard let filePath = fileURL, error == nil else {
254
+
255
+ print("Error from operation: (error?.localizedDescription ?? "No Error")")
256
+
257
+ return
258
+
259
+ }
260
+
261
+ print("** Operation: (operationIndex) finished with downloaded file: (filePath)")
262
+
263
+ }
264
+
265
+ func notifyOfNetworkProgress(progress: String, operationIndex: Int) {
266
+
267
+ print("-- Operation: (operationIndex) : (progress)")
268
+
269
+ }
270
+
271
+ }
108
272
 
109
273
  ```
110
274