Skip to content

Instantly share code, notes, and snippets.

@stinger
Last active March 25, 2023 22:12
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save stinger/420107a71a02995c312036eb7919e9f9 to your computer and use it in GitHub Desktop.
Save stinger/420107a71a02995c312036eb7919e9f9 to your computer and use it in GitHub Desktop.
Swift 3: URLSessionDelegate
//: # Swift 3: URLSessionDelegate
//: The following example shows how to use `OperationQueue` to queue the network requests. This is useful in many ways (for delaying queued requests when the networking goes down for example)
import Foundation
import PlaygroundSupport
class Requester:NSObject {
let opQueue = OperationQueue()
var response:URLResponse?
var session:URLSession?
var time:DispatchTime! {
return DispatchTime.now() + 1.0 // seconds
}
func request() {
print("Requesting...")
// suspend the OperationQueue (operations will be queued but won't get executed)
self.opQueue.isSuspended = true
let sessionConfiguration = URLSessionConfiguration.default
// disable the caching
sessionConfiguration.urlCache = nil
// initialize the URLSession
self.session = URLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: self.opQueue)
// create a URLRequest with the given URL and initialize a URLSessionDataTask
if let url = URL(string: "https://localhost/uploader/redirect.php") {
let request = URLRequest(url: url)
if let task = self.session?.dataTask(with: request) {
// start the task, tasks are not started by default
task.resume()
}
}
// Open the operations queue after 1 second
DispatchQueue.main.asyncAfter(deadline: self.time, execute: {[weak self] in
print("Opening the OperationQueue")
self?.opQueue.isSuspended = false
})
}
}
extension Requester:URLSessionDelegate {
func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
// We've got a URLAuthenticationChallenge - we simply trust the HTTPS server and we proceed
print("didReceive challenge")
completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
}
func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
// We've got an error
if let err = error {
print("Error: \(err.localizedDescription)")
} else {
print("Error. Giving up")
}
PlaygroundPage.current.finishExecution()
}
}
extension Requester:URLSessionDataDelegate {
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didBecome streamTask: URLSessionStreamTask) {
// The task became a stream task - start the task
print("didBecome streamTask")
streamTask.resume()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didBecome downloadTask: URLSessionDownloadTask) {
// The task became a download task - start the task
print("didBecome downloadTask")
downloadTask.resume()
}
func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
// We've got a URLAuthenticationChallenge - we simply trust the HTTPS server and we proceed
print("didReceive challenge")
completionHandler(.useCredential, URLCredential(trust: challenge.protectionSpace.serverTrust!))
}
func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: (URLRequest?) -> Void) {
// The original request was redirected to somewhere else.
// We create a new dataTask with the given redirection request and we start it.
if let urlString = request.url?.absoluteString {
print("willPerformHTTPRedirection to \(urlString)")
} else {
print("willPerformHTTPRedirection")
}
if let task = self.session?.dataTask(with: request) {
task.resume()
}
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
// We've got an error
if let err = error {
print("Error: \(err.localizedDescription)")
} else {
print("Error. Giving up")
}
PlaygroundPage.current.finishExecution()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: (URLSession.ResponseDisposition) -> Void) {
// We've got the response headers from the server.
print("didReceive response")
self.response = response
completionHandler(URLSession.ResponseDisposition.allow)
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
// We've got the response body
print("didReceive data")
if let responseText = String(data: data, encoding: .utf8) {
print(self.response)
print("\nServer's response text")
print(responseText)
}
do {
let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
if let firstCategory = json["categories"]??[0]["name"] as? String {
print("The first category in the JSON list is \"\(firstCategory)\"")
}
} catch let error as NSError {
print("Error parsing JSON: \(error.localizedDescription)")
}
self.session?.finishTasksAndInvalidate()
PlaygroundPage.current.finishExecution()
}
}
PlaygroundPage.current.needsIndefiniteExecution = true
let requester = Requester()
requester.request()
@OctoberHammer
Copy link

How should I change theese lines for Swift 3 & Xcode 8.2:

		let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers)
		if let firstCategory = json["categories"]??[0]["name"] as? String

?

@arunlj561
Copy link

It will create a retain cycle, as delegate is set to self and self is strong.
i.e. let requester = Requester() // is strong variable

    self.session = URLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: self.opQueue)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment