-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Make URLSession and URLSessionTask more source-compatible with Darwin #2587
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -268,7 +268,7 @@ open class URLSession : NSObject { | |
} | ||
|
||
open private(set) var delegateQueue: OperationQueue | ||
open var delegate: URLSessionDelegate? | ||
open private(set) var delegate: URLSessionDelegate? | ||
open private(set) var configuration: URLSessionConfiguration | ||
|
||
/* | ||
|
@@ -370,8 +370,13 @@ open class URLSession : NSObject { | |
} | ||
} | ||
|
||
@available(*, unavailable, renamed: "getTasksWithCompletionHandler(_:)") | ||
open func getTasksWithCompletionHandler(completionHandler: @escaping ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask]) -> Void) { | ||
getTasksWithCompletionHandler(completionHandler) | ||
} | ||
|
||
/* invokes completionHandler with outstanding data, upload and download tasks. */ | ||
open func getTasksWithCompletionHandler(completionHandler: @escaping ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask]) -> Void) { | ||
open func getTasksWithCompletionHandler(_ completionHandler: @escaping ([URLSessionDataTask], [URLSessionUploadTask], [URLSessionDownloadTask]) -> Void) { | ||
Comment on lines
+373
to
+379
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Darwin Foundation doesn't use an argument label. Marked the old version as |
||
workQueue.async { | ||
self.delegateQueue.addOperation { | ||
var dataTasks = [URLSessionDataTask]() | ||
|
@@ -419,6 +424,22 @@ open class URLSession : NSObject { | |
open func dataTask(with url: URL) -> URLSessionDataTask { | ||
return dataTask(with: _Request(url), behaviour: .callDelegate) | ||
} | ||
|
||
/* | ||
* data task convenience methods. These methods create tasks that | ||
* bypass the normal delegate calls for response and data delivery, | ||
* and provide a simple cancelable asynchronous interface to receiving | ||
* data. Errors will be returned in the NSURLErrorDomain, | ||
* see <Foundation/NSURLError.h>. The delegate, if any, will still be | ||
* called for authentication challenges. | ||
*/ | ||
open func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask { | ||
return dataTask(with: _Request(request), behaviour: .dataCompletionHandler(completionHandler)) | ||
} | ||
|
||
open func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask { | ||
return dataTask(with: _Request(url), behaviour: .dataCompletionHandler(completionHandler)) | ||
} | ||
Comment on lines
+427
to
+442
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved these from an extension to the class itself. With Darwin Foundation we're able to override these methods in subclasses. Same with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SE-0117 strikes again. I think you can mark each method in the extension with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. They were already There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I didn't double checked my proposal. I just tested in a small Xcode (Mac) project that reproduces the problem, and I get this error "Overriding non- Do you think that might be a better solution? I don't mind moving the methods into the main class code, but if someone wrote them as an extension for organization, I would prefer to keep them that one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I’m afraid There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's true. What a strange limitation of extensions. I wonder why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAIK this has to do with method dispatch. We can't retroactively add methods to class vtable, unless we use some completely different dispatching mechanism, like message passing in Objective-C. That's why |
||
|
||
/* Creates an upload task with the given request. The body of the request will be created from the file referenced by fileURL */ | ||
open func uploadTask(with request: URLRequest, fromFile fileURL: URL) -> URLSessionUploadTask { | ||
|
@@ -437,6 +458,18 @@ open class URLSession : NSObject { | |
let r = URLSession._Request(request) | ||
return uploadTask(with: r, body: nil, behaviour: .callDelegate) | ||
} | ||
|
||
/* | ||
* upload convenience method. | ||
*/ | ||
open func uploadTask(with request: URLRequest, fromFile fileURL: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionUploadTask { | ||
let fileData = try! Data(contentsOf: fileURL) | ||
return uploadTask(with: request, from: fileData, completionHandler: completionHandler) | ||
} | ||
|
||
open func uploadTask(with request: URLRequest, from bodyData: Data?, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionUploadTask { | ||
return uploadTask(with: _Request(request), body: .data(createDispatchData(bodyData!)), behaviour: .dataCompletionHandler(completionHandler)) | ||
} | ||
|
||
/* Creates a download task with the given request. */ | ||
open func downloadTask(with request: URLRequest) -> URLSessionDownloadTask { | ||
|
@@ -453,6 +486,24 @@ open class URLSession : NSObject { | |
open func downloadTask(withResumeData resumeData: Data) -> URLSessionDownloadTask { | ||
return invalidDownloadTask(behavior: .callDelegate) | ||
} | ||
|
||
/* | ||
* download task convenience methods. When a download successfully | ||
* completes, the URL will point to a file that must be read or | ||
* copied during the invocation of the completion routine. The file | ||
* will be removed automatically. | ||
*/ | ||
open func downloadTask(with request: URLRequest, completionHandler: @escaping (URL?, URLResponse?, Error?) -> Void) -> URLSessionDownloadTask { | ||
return downloadTask(with: _Request(request), behavior: .downloadCompletionHandler(completionHandler)) | ||
} | ||
|
||
open func downloadTask(with url: URL, completionHandler: @escaping (URL?, URLResponse?, Error?) -> Void) -> URLSessionDownloadTask { | ||
return downloadTask(with: _Request(url), behavior: .downloadCompletionHandler(completionHandler)) | ||
} | ||
|
||
open func downloadTask(withResumeData resumeData: Data, completionHandler: @escaping (URL?, URLResponse?, Error?) -> Void) -> URLSessionDownloadTask { | ||
return invalidDownloadTask(behavior: .downloadCompletionHandler(completionHandler)) | ||
} | ||
|
||
/* Creates a bidirectional stream task to a given host and port. | ||
*/ | ||
|
@@ -556,64 +607,6 @@ fileprivate extension URLSession { | |
} | ||
} | ||
|
||
|
||
/* | ||
* URLSession convenience routines deliver results to | ||
* a completion handler block. These convenience routines | ||
* are not available to URLSessions that are configured | ||
* as background sessions. | ||
* | ||
* Task objects are always created in a suspended state and | ||
* must be sent the -resume message before they execute. | ||
*/ | ||
extension URLSession { | ||
/* | ||
* data task convenience methods. These methods create tasks that | ||
* bypass the normal delegate calls for response and data delivery, | ||
* and provide a simple cancelable asynchronous interface to receiving | ||
* data. Errors will be returned in the NSURLErrorDomain, | ||
* see <Foundation/NSURLError.h>. The delegate, if any, will still be | ||
* called for authentication challenges. | ||
*/ | ||
open func dataTask(with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask { | ||
return dataTask(with: _Request(request), behaviour: .dataCompletionHandler(completionHandler)) | ||
} | ||
|
||
open func dataTask(with url: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask { | ||
return dataTask(with: _Request(url), behaviour: .dataCompletionHandler(completionHandler)) | ||
} | ||
|
||
/* | ||
* upload convenience method. | ||
*/ | ||
open func uploadTask(with request: URLRequest, fromFile fileURL: URL, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionUploadTask { | ||
let fileData = try! Data(contentsOf: fileURL) | ||
return uploadTask(with: request, from: fileData, completionHandler: completionHandler) | ||
} | ||
|
||
open func uploadTask(with request: URLRequest, from bodyData: Data?, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionUploadTask { | ||
return uploadTask(with: _Request(request), body: .data(createDispatchData(bodyData!)), behaviour: .dataCompletionHandler(completionHandler)) | ||
} | ||
|
||
/* | ||
* download task convenience methods. When a download successfully | ||
* completes, the URL will point to a file that must be read or | ||
* copied during the invocation of the completion routine. The file | ||
* will be removed automatically. | ||
*/ | ||
open func downloadTask(with request: URLRequest, completionHandler: @escaping (URL?, URLResponse?, Error?) -> Void) -> URLSessionDownloadTask { | ||
return downloadTask(with: _Request(request), behavior: .downloadCompletionHandler(completionHandler)) | ||
} | ||
|
||
open func downloadTask(with url: URL, completionHandler: @escaping (URL?, URLResponse?, Error?) -> Void) -> URLSessionDownloadTask { | ||
return downloadTask(with: _Request(url), behavior: .downloadCompletionHandler(completionHandler)) | ||
} | ||
|
||
open func downloadTask(withResumeData resumeData: Data, completionHandler: @escaping (URL?, URLResponse?, Error?) -> Void) -> URLSessionDownloadTask { | ||
return invalidDownloadTask(behavior: .downloadCompletionHandler(completionHandler)) | ||
} | ||
} | ||
|
||
internal extension URLSession { | ||
/// The kind of callback / delegate behaviour of a task. | ||
/// | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -376,7 +376,7 @@ open class URLSessionTask : NSObject, NSCopying { | |
/* | ||
* The current state of the task within the session. | ||
*/ | ||
open var state: URLSessionTask.State { | ||
open fileprivate(set) var state: URLSessionTask.State { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
get { | ||
return self.syncQ.sync { self._state } | ||
} | ||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
URLSession.delegate
is get-only in Darwin Foundation.Therefore, we should be able to override it with a get-only property. We can't do this with swift-corelibs-foundation now.