Preventing NSURLConnection Cache Issues

If you have worked with the NSURLConnection class in iOS, then you may have come across this behaviour before; we were using the NSURLConnection class to download a remote XML file to check if there was an update for our app. When we changed the XML file on the remote server to indicate there was indeed an update, the iOS application still reported that there was no update.

It turns out that you can specify a caching policy for the NSURLRequest that you pass into NSURLConnection. If you don’t specify anything (as in my case) then NSURLConnection will obey the instructions in the header of the response from the server.

From the Apple Documentation, you can specify one of the following options for the NSURLRequestCachePolicy that you pass into your NSURLRequest:

NSURLRequestUseProtocolCachePolicy: This is the default value and means that depending on what the protocol dictates, the best fitting policy will be used. You can use the “Cache-Control” and “Expires” header values that the server returns to control how iOS will cache the data. For example, if you don’t want it to cache at all, you can set the “Expires” date equal to the Date header value and “Cache-Control: max-age=0”. Check the HTTP Standards for more information.

NSURLRequestReloadIgnoringCacheData: With this setting, it will ignore local cache and retrieve the data from the source again. This is what we should have specified for retrieving remote config files.

NSURLRequestReturnCacheDataElseLoad: This setting will use a local cached copy of the data if it exists; otherwise, it will load the data from the source. This would be ideal for data that doesn’t change and just needs to be retrieved once.

NSURLRequestReturnCacheDataDontLoad: This will return a local cached copy of the data if it exists. If the data doesn’t exist in local cache, then it will return nil. It won’t attempt to retrieve the data from the source. This would be ideal for an offline mode of a news app for example.

In my case, I had not specifically set a cache policy in my NSURLRequest and the server that my XML file was sitting on did not specified a “Cache-Control:max-age” value too high so when my app was checking for updates, it was getting stale data.

We considered three different options for correcting this issue:

1. Set a caching policy on your NSURLRequest instance. This is the preferred solution and this gives you control over different caching policies depending on the resource you’re fetching.

2. Set the cache-control and expires header values in the response from the server. You’d only be able to do this for if you have control of the server.

3. You can add a random query string variable to your request URL. This will be treated as a unique and new URL. Although this solution works, it’s not ideal since Apple has provided a way via option #1 to control caching.

If you forgot to specify a cache policy for your NSURLRequest instance and your iPhone or iPad application is already in production/in the App Store, then your best bet would be to update the response headers from your server. If you don’t control the server, then you’re probably in damage control mode; update your app description and tell your users that there’s a fix coming soon!

129 thoughts on “Preventing NSURLConnection Cache Issues”

  1. I am trying to upload a React Native mobile app with Rails backend to an iOS emulator and have been seeing an error message that no bundler URL is present. Several posts on SO pointed to the appDelegate.m file as being related. I changed the jsCodelocation but had no change. Is the appDelegate.m like the entry file? It kinda looks like a bundle type file.

  2. hi.
    it shows ” ARC Semantic issue” at this part ” [self.firstDiceView showDice:roll];
    [self.secondDiceView showDice:roll2];

    ” and i couldnt sove whats wrong in this code. ive checked all the spelling tho

  3. Great tutorial! I’ve got to the point where I should be seeing the basic table presented at the end of 4.4, updating for swift 3 as I go, but can’t seem to get things just right. Wondering if there is any update here or whether I can post my codefor support? (specifically HomeModel.swift)

    On a completely separate note, does anyone know whether the intermediate course deals with more in depth tutorials surrounding databases?

    Thanks in advance kind strangers!

  4. I have made a project with Objective C, but it is not running on different mac os,what is the problem ,pls help me asap

        • Chris, has this tutorial been updated to include Swift 3 and WKWebView? I’m specifically interested in building a webview app for my word press website so this would be the determining factor on whether or not I’d want to buy in.

  5. Hey Chris, thanks a ton, one of the best and simple tutorials. I just have a question, if I have two tables: categories, and quotes. I retrieve the categories like locations in your tutorial, but depending on the category the user chooses, I want to retrieve the quotes, my SQL statement would be “SELECT * FROM quotes WHERE category=’categoryExample'”. Now, how would I change the php and let the server know what I am requesting dynamically? Thanks in advance

  6. I have a question: I started my first cxode project, for which I used youre tutorial for soundboard app but when I run it in the iphone on my mac (the standard command run) it shows the app but it isn’t scaled good! how can I fix this?

  7. I just want it to play sound, not open an app. what is the code to do this? i just want to play an mp3 file using the main.cpp file. is there no 1 line code to do this simple task??

  8. I am having running into several errors regarding my HomeModel.swift file and my viewcontroller. Is there any updated version of HomeModel for swift 3 and Xcode 8.2.1? This would be incredibly helpful!

  9. Excellent tutorial, thank you Chris.
    However when I create the solution I do not see the header file .h or .m anywhere. I have Xcode 8.2.1

  10. The code is working well for me in swift 3, but i have the problem that it keeps old data in the cache (it shows data even if i don’t have internet connection). I know you have talked about it, but i don’t know where to change the caching policy of the URLRequest instance

  11. My main concern is do these app builders display the wordpress plugins? Specifically Visual Composer or other layout plugins that house content areas?

  12. Are there newer instructions for this. Do you need a paid developer account and what about the newest xcode version. What is different?

  13. Hey Chris I keep getting a “thread 1: breakpoint 1.1” message in a green highlighted line of code in this function:

    func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    return pickerData[row]
    }

    With Swift 3 on Xcode 8.2.1 it required me to alter the code to:

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    return pickerData[row]
    }

    I can’t seem to find the error nor the sollution to this problem.

  14. Hey Chris. So, when using this method to create apps, are you basically having to create these intermediate PHP pages for everything you want your app to do? i.e. if, on my website, I have a profile page, to display the profile page in my app, I also have to create an intermediary (service) PHP page for the app to interact with just for that profile page and if I want the user to login, I need a login/auth service page for each “page” within the app? Thanks for your help!

    • Exactly that’s what i have been trying to do and works fine since you’re trying to pull different information for different view controller. Hope there’s no other option i have seen so far rather than specifying different end points. @CraigLil:disqus

        • Yap, same way sir but ensure you protect your moving data with https and other security methods to prevent theft in API keys and all sensitve data

  15. hello Chris
    I am getting this response in console but i want to get status value and use it to check with url and then navigate to next view controller..Thanks for help .

    {“status”:”success”,”user_id”:”58″,”user_name”:”Kundan”,”result”:”You have been logged in successfully”}

    • i have checked with url and now it is working but when i entering username or password in textfield and after that if their is space the app crashes. How can i fix this problem. Plz Chris reply it’s urgent ?

  16. Nice article! However I’m struggling with the HomeModel. I’ve followed all the Swift3 suggestions, but still get 2 errors I can’t figger out. I added a screenshot as reference.
    Error 1: ‘URLSession’ produces'()’, not th expected contextual result type ‘URLSession!’
    Error 2: Value of type ‘HomeModel’ has no member ‘parseJSON’

    Anyone knows how to solve this?

    https://uploads.disquscdn.com/images/67a46fd59b9029706c488e7c36d3a6f08f12caff34a12a4be0709a42039c6244.png

Leave a Comment

Share
Tweet
Pin