Skip to content

Commit 5d5036e

Browse files
author
Pushkar Kulkarni
committed
Implementation of URLSessionTask.cancel()
1 parent 6651025 commit 5d5036e

File tree

2 files changed

+52
-11
lines changed

2 files changed

+52
-11
lines changed

Foundation/NSURLSession/NSURLSessionTask.swift

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,21 @@ open class URLSessionTask : NSObject, NSCopying {
202202
* cases, the task may signal other work before it acknowledges the
203203
* cancelation. -cancel may be sent to a task that has been suspended.
204204
*/
205-
open func cancel() { NSUnimplemented() }
206-
205+
open func cancel() {
206+
workQueue.sync {
207+
guard self.state == .running || self.state == .suspended else { return }
208+
self.state = .canceling
209+
self.workQueue.async {
210+
guard let s = self.session as? URLSession else { fatalError() }
211+
guard let delegate = s.delegate as? URLSessionTaskDelegate else { fatalError() }
212+
s.delegateQueue.addOperation {
213+
delegate.urlSession(s, task: self, didCompleteWithError: NSError(domain: NSURLErrorDomain, code: NSURLErrorCancelled, userInfo: nil))
214+
self.internalState = .taskCompleted
215+
}
216+
}
217+
}
218+
}
219+
207220
/*
208221
* The current state of the task within the session.
209222
*/

TestFoundation/TestNSURLSession.swift

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ class TestURLSession : XCTestCase {
2929
("test_downloadTaskWithURLRequest", test_downloadTaskWithURLRequest),
3030
("test_downloadTaskWithRequestAndHandler", test_downloadTaskWithRequestAndHandler),
3131
("test_downloadTaskWithURLAndHandler", test_downloadTaskWithURLAndHandler),
32-
("test_finishTaskAndInvalidate", test_finishTasksAndInvalidate)
32+
("test_finishTaskAndInvalidate", test_finishTasksAndInvalidate),
33+
("test_cancelTask", test_cancelTask),
3334
]
3435
}
3536

@@ -262,6 +263,27 @@ class TestURLSession : XCTestCase {
262263
session.finishTasksAndInvalidate()
263264
waitForExpectations(timeout: 12)
264265
}
266+
267+
func test_cancelTask() {
268+
let serverReady = ServerSemaphore()
269+
globalDispatchQueue.async {
270+
do {
271+
try self.runServer(with: serverReady)
272+
} catch {
273+
XCTAssertTrue(true)
274+
return
275+
}
276+
}
277+
serverReady.wait()
278+
let url = URL(string: "http://127.0.0.1:\(serverPort)/Peru")!
279+
let d = DataTask(with: expectation(description: "Task to be canceled"))
280+
d.dataTaskExpectation.fulfill() //we aren't interested in this expectation
281+
d.cancelExpectation = expectation(description: "URLSessionTask wasn't canceled")
282+
d.run(with: url)
283+
d.cancel()
284+
waitForExpectations(timeout: 12)
285+
}
286+
265287
}
266288

267289
class SessionDelegate: NSObject, URLSessionDelegate {
@@ -279,6 +301,8 @@ class DataTask : NSObject {
279301
var capital = "unknown"
280302
var session: URLSession! = nil
281303
var task: URLSessionDataTask! = nil
304+
var cancelExpectation: XCTestExpectation?
305+
282306
public var error = false
283307

284308
init(with expectation: XCTestExpectation) {
@@ -300,20 +324,24 @@ class DataTask : NSObject {
300324
task = session.dataTask(with: url)
301325
task.resume()
302326
}
327+
328+
func cancel() {
329+
task.cancel()
330+
}
303331
}
304332

305333
extension DataTask : URLSessionDataDelegate {
306-
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
307-
capital = String(data: data, encoding: String.Encoding.utf8)!
308-
dataTaskExpectation.fulfill()
309-
}
334+
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
335+
capital = String(data: data, encoding: String.Encoding.utf8)!
336+
dataTaskExpectation.fulfill()
337+
}
310338
}
311339

312340
extension DataTask : URLSessionTaskDelegate {
313-
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: NSError?) {
314-
guard let e = error else { return }
315-
XCTAssertEqual(e.code, NSURLErrorTimedOut, "Unexpected error code")
316-
dataTaskExpectation.fulfill()
341+
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
342+
if let cancellation = cancelExpectation {
343+
cancellation.fulfill()
344+
}
317345
self.error = true
318346
}
319347
}

0 commit comments

Comments
 (0)