Hi guys,
Is there an issue for caching on 8.x ?
this:
public func URLSession(
session: NSURLSession,
dataTask: NSURLSessionDataTask,
willCacheResponse proposedResponse: NSCachedURLResponse,
completionHandler: ((NSCachedURLResponse?) -> Void))
{
if let dataTaskWillCacheResponse = dataTaskWillCacheResponse {
completionHandler(dataTaskWillCacheResponse(session, dataTask, proposedResponse))
} else if let delegate = self[dataTask] as? Request.DataTaskDelegate {
delegate.URLSession(
session,
dataTask: dataTask,
willCacheResponse: proposedResponse,
completionHandler: completionHandler
)
} else {
completionHandler(proposedResponse)
}
}
is never called in iOS 8.X but it's is in iOS 9.X...i have nothing in my code to differentiate iOS 8 and 9 (maybe that's the issue)
I'm currently on Alamofire 3.2.1 maybe the 3.3 fixed the issue but i didn't to go to swift 2.2 right now..
Thanks for future answers
Hmmmm....we'll need to look into this @Mycose. Is there any chance you could put together a failing test to demonstrate the issue? That would make it much easier for us to troubleshoot.
Sure but do you have any idea how i can demonstrate the issue ?
I dont have any error in the logs, it's just that the cache worked on iOS 9 and not iOS 8
i can post you some of the code we are using:
Our service class:
import Foundation
import Alamofire
class MyCCHTTPService: NSObject {
var manager : Manager?
var cachePolicy : NSURLRequestCachePolicy = .UseProtocolCachePolicy
var cacheDuration : NSTimeInterval = 24*60*60
var timeOut : NSTimeInterval = 30
var debugMode : Bool = false
override init(){
super.init()
self.manager = Manager(configuration: urlSessionConfiguration())
self.manager?.delegate.dataTaskWillCacheResponse = {
(urlSession : NSURLSession, dataTask : NSURLSessionDataTask, cachedResponse : NSCachedURLResponse) -> NSCachedURLResponse in
let response = cachedResponse.response as! NSHTTPURLResponse
var headers = response.allHeaderFields as! [String : String]
headers.removeValueForKey("Expires")
headers.removeValueForKey("s-maxage")
headers["Cache-Control"] = String(format: "max-age=%li",self.cacheDuration)
let modifiedResponse = NSHTTPURLResponse(
URL: response.URL!,
statusCode: response.statusCode,
HTTPVersion: "HTTP/1.1",
headerFields: headers)
let modifiedCachedResponse = NSCachedURLResponse(
response: modifiedResponse!,
data: cachedResponse.data,
userInfo: cachedResponse.userInfo,
storagePolicy: cachedResponse.storagePolicy)
return modifiedCachedResponse
}
}
private func urlSessionConfiguration() -> NSURLSessionConfiguration{
let urlSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
urlSessionConfiguration.requestCachePolicy = cachePolicy
urlSessionConfiguration.timeoutIntervalForResource = timeOut
urlSessionConfiguration.timeoutIntervalForRequest = timeOut
return urlSessionConfiguration
}
func logOperation<T>(response : Response<T,NSError>){
if(self.debugMode){
print(response.debugDescription)
}
}
}
Our router class:
import Alamofire
import Foundation
enum CMSRouter: URLRequestConvertible {
static let hostURL = NSURL(string: NSUserDefaults.standardUserDefaults().objectForKey(NSUserDefaults.SettingsKeys.CMS, forceLoadSettings: true) as! String)!
static let baseURL = NSURL(string: "/base/url",relativeToURL: hostURL)
var URL : NSURL { return CMSRouter.baseURL!.URLByAppendingPathComponent(route.path) }
// Router Cases
case ActiveStores
case EmailDomain
case Languages(String)
case FieldControlDisplay(String)
case Texts(String,String)
case Titles(String,String)
case Countries(String,String)
case Nationalities(String,String)
case AddressFieldsOrder(String,String)
case ClientType
// MARK: Route from cases
var route : (path: String, parameters: [String: AnyObject]?) {
switch self{
case .ActiveStores:
return ("/api1",nil)
case .EmailDomain:
return ("/api2",nil)
case .Languages(let zoneCode):
return ("/api3/\(zoneCode)",nil)
case .FieldControlDisplay(let zoneCode):
return ("/api4/\(zoneCode)",nil)
case .Texts(let zoneCode, let lang):
return ("/api5/\(zoneCode)/\(lang)",nil)
case .Titles(let zoneCode, let lang):
return ("/api6/\(zoneCode)/\(lang)",nil)
case .Countries(let zoneCode, let lang):
return ("/api7/\(zoneCode)/\(lang)",nil)
case .Nationalities(let zoneCode, let lang):
return ("/api8/\(zoneCode)/\(lang)",nil)
case .AddressFieldsOrder(let zoneCode, let lang):
return ("/api9/\(zoneCode)/\(lang)",nil)
case .ClientType:
return ("/api10/",nil)
}
}
var URLRequest: NSMutableURLRequest {
return
Alamofire
.ParameterEncoding
.URL
.encode(NSURLRequest(URL: URL), parameters: route.parameters).0
}
}
And the service child which implement the functions we are calling:
import Foundation
import Alamofire
class MyCCCMSHTTPService: MyCCHTTPService, MyCCCMSService {
// MARK: configuration/stores/active
func fetchStoresActive(completionHandler : CountryStores -> Void, failureHandler : NSError -> Void) -> Void{
self.manager!.request(CMSRouter.ActiveStores)
.responseModelRocketJSON { (response : Response<CountryStores,NSError>) -> Void in
self.logOperation(response)
if(response.result.error != nil){
failureHandler(response.result.error!)
}
else{
completionHandler(response.result.value!)
}
};
}
so the problem is that self.manager?.delegate.dataTaskWillCacheResponse is never used on iOS8...
I got nothing to specify to use cache, and receiving nothing in the response header. For iOS 9 it's works perfectly :/
Thanks for all the info you provided here.
We have a fairly large set of CacheTests to help verify this type of behavior. If you open up the test suite and run this test on iOS 8.x or iOS 9.x and set a breakpoint in the URLSession(_:dataTask:willCacheResponse:completionHandler:) method, you'll see that the breakpoint is being called each time.
I then added your delegate.dataTaskWillCacheResponse override to the test's manager and re-ran. Both the delegate method and the override closure are being called as expected.
The only difference may be that I'm running Alamofire 3.3.1 and you are running 3.2.1. We have made some changes in the 3.3.1 release that fixed some bugs around some of the delegate methods being called, but this particular session delegate method should not have been affected. Additionally, the bugs there should have only affected the 3.3.0 release, not the 3.2.1 release. Either way, I'd encourage you to dig into the tests that I've linked in this comment to see the behavior working for yourself. Then I would update to 3.3.1 and see if that fixes your issue.
If 3.3.1 does not fix your issue, then you'll need to figure out why your logic is different than the logic in the tests. I don't see anything obvious from the code you posted, but that doesn't mean that you don't have something else set that is affecting the behavior that isn't in your example.
At this point, I don't see an issue in Alamofire. All the behavior you've reported is not working seems to be working correctly from what I can tell. Because of this, I'm going to close this issue out for now. If you do still continue to have issues, then please provide a failing test or sample project for us and attach it to this issue. Then we'll gladly re-open the issue and continue to help you investigate further.
Best of luck! 馃嵒
Hello, thanks for the link to tests, really great
I tried and check a lot with the test to so what the problem was. The test are working great with iOS 8 and 9 so it's not coming from here. So i just the problem is coming from the fact that my response has nothing about cache in the headers
Since i can't touch the server i did a fix by stocking in the NSSharedCache manually the response and it's working ^^
Cool...thanks for the update!
Most helpful comment
Sure but do you have any idea how i can demonstrate the issue ?
I dont have any error in the logs, it's just that the cache worked on iOS 9 and not iOS 8
i can post you some of the code we are using:
Our service class:
Our router class:
And the service child which implement the functions we are calling:
so the problem is that self.manager?.delegate.dataTaskWillCacheResponse is never used on iOS8...
I got nothing to specify to use cache, and receiving nothing in the response header. For iOS 9 it's works perfectly :/