the sample code below. it normally works fine after the first blocking (i.e. after i kill the app and launch it again). i guess this is some sort of caching, despite of the "reloadIgnoringLocalAndRemoteCacheData" flag. to defeat this caching just change the url ever so slightly (e.g. increase pageSize by 1). the app works normally with small page sizes. note that i used this particular URL just as a guinea pig for the test.
import Foundation
class C: NSObject {
private var session: URLSession!
private let someSerialQueue: DispatchQueue
private let otherSerialQueue: DispatchQueue
private let someOperationQueue: OperationQueue
override init() {
someSerialQueue = DispatchQueue(label: "someSerialQueue")
otherSerialQueue = DispatchQueue(label: "otherSerialQueue")
someOperationQueue = OperationQueue()
someOperationQueue.maxConcurrentOperationCount = 1
someOperationQueue.underlyingQueue = someSerialQueue
super.init()
}
func test() {
let pageSize = 90
let testEndpoint = "https://api.github.com/search/repositories?q=created:%3E2021-08-13&sort=stars&order=desc&accept=application/vnd.github.v3+json&per_page=\(pageSize)"
URLCache.shared.removeAllCachedResponses()
var request = URLRequest(url: URL(string: testEndpoint)!)
request.timeoutInterval = 5
request.httpShouldUsePipelining = true
request.cachePolicy = .reloadIgnoringLocalAndRemoteCacheData
session = URLSession(configuration: .default, delegate: self, delegateQueue: someOperationQueue)
let task = session.dataTask(with: request)
task.resume()
}
}
extension C: URLSessionTaskDelegate {
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let error = error {
print("TaskDelegate: didCompleteWithError: \(error)")
} else {
print("TaskDelegate: didComplete with no error")
}
}
}
extension C: URLSessionDataDelegate {
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, willCacheResponse proposedResponse: CachedURLResponse, completionHandler: @escaping (CachedURLResponse?) -> Void) {
completionHandler(nil)
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
let status = (response as! HTTPURLResponse).statusCode
print("DataDelegate: didReceive response. status: \(status)")
completionHandler(.becomeStream)
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didBecome streamTask: URLSessionStreamTask) {
print("DataDelegate: didBecome streamTask")
streamTask.captureStreams()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
fatalError("DataDelegate: shall not happen")
}
}
extension C: URLSessionStreamDelegate {
func urlSession(_ session: URLSession, streamTask: URLSessionStreamTask, didBecome inputStream: InputStream, outputStream: OutputStream) {
print("StreamDelegate: didBecome inputStream / outputStream")
inputStream.open()
otherSerialQueue.async {
print("b4 JSONSerialization.jsonObject")
let object = try! JSONSerialization.jsonObject(with: inputStream, options: [])
print("after JSONSerialization.jsonObject")
let len = "\(object)".count
print("got JSON, \(len) bytes")
}
}
}
let c = C()
c.test()
while true {
print("run loop run")
RunLoop.main.run()
}