EVURLCache - a NSURLCache subclass for handling all web requests that use NSURLRequest

Overview

EVURLCache

Build Status Issues Documentation Stars Awesome

Version Language Platform Support License

Git Twitter LinkedIn Website eMail

What is this?

This is a NSURLCache subclass for handeling all web requests that use NSURLRequest. (This includes UIWebView)

The EVURLCache is meant for handeling the following caching strategies:

  • The app has to be functional even if there is no internet connection.
  • The app has to be functional right after the app has been downloaden from the app store. (This means that the required content can be included in the app.)
  • You do want to be a able to download new/updated content if it's available.

Extra functionality

Since (most likely, see limitations) all files will be cached, you do not have to handle incoming data yourself. You can do a NSURLRequest and then in the connectionDidFinishLoading you can use the file from the cache. You can get the full path of that file by calling: EVURLCache.storagePathForRequest(theRequest)

Controlling the cache

EVURLCache respects the HTTP header variables 'Cache-Control' and 'Pragma' when these contain 'no-cache' or 'no-store' then the response will not be written to the cache. You do have to be aware that if the file is already in the cache because you have put it in the PreCache folder yourself or the file was previously fetched with different header variables, the file will be written to the cache in order to update it's contents and the HTTP header varialbes will be ignored.

EVURLCache will also take into account the HTTP header variable 'Access-Control-Max-Age' when reading from the cache. When the content is older it will try to fetch it again.

Caching is done based on the complete URL including the querystring parameters. If for some reason you want multiple URL's to be stored and fetched as the same cache item, then you can add the HTTP header variable (server side) MobileAppCacheKey

Most webservers interpit url's' case insesnsitive. Since iOS and OSX (not always) have a case sensitive file system it could be that a URL is requested that do not have a case sensitive match on the file system. By default EVURLCache stores all files while converting the path to lowercase. If you do want a case sensitive match, then you could set the EVURLCache.FORCE_LOWERCASE to false

You can influence the maximum file size that will be cached by EVURLCache. This is a setting that is handled by the NSURLCache base class. By default it's set to 16MB. You can influence this by setting the EVURLCache.MAX_FILE_SIZE. It's set as number of bits. So setting it to 24 will mean a cache size of 2^24 = 16MB

You can influence the maximum total size that will be cached by EVURLCache. This is a setting that is handled by the NSURLCache base class. By default it's set to 256MB. You can influence this by setting the EVURLCache.MAX_CACHE_SIZE It's set as number of bits. So setting it to 30 will mean a cache size of 2^30 = 256MB. Make sure it's at least 16 times larger than the Maximum file size or the maximum file size will not be used

If you want to see what EVURLCache is doing, then set EVURLCache.LOGGING to true

See the demo in action

Follow these steps to see the demo app in action. Logging is enabled, so watch the output window to see what's happening.

  • Make sure the demo app is not on your phone and set it in airplaine mode.
  • Start up the app. You should still see the homepage of my website because it's in the PreCache
  • Select any other page from the menu. You won't see anything happening because none of these are in the PreCache or Cache folder
  • Turn airplaine mode off and select a menu option. You will then just see that page.
  • Turn airplaine mode on and navigate back to the homepage. You can now also go to the page you selected in the previous step becaus it has been cached. Other pages are still unavailable.

Creating the initial cache

Just put all the files that you want to be available from the start in the folder /PreCache. The directory required directory structure will be the same as the complete url. So evict.nl/ios/samples/index.html has to be stored in the /PreCache/evict.nl/ios/samples/ folder. The easiest way to add this to your project is to select 'add files' and then select the folder and select 'create folder reference for any added folders'

If you are not sure what files you would need to include in the PreCache folder, then just run your app with the EVURLCache enabled in the simulator and execute all the functions that needs to be functional without an internet connection. Then browse to the files (see ~/Library/Application Support/iPhone Simulator/ ...) The downloaded files will be in the Documents/Cache folder. See the output window for the exact location (if debugging is enabled). You can copy these files to the PreCache folder

Compatibility

This cache should work with all download libraries that use a NSURLRequest for downloading from the web (Like AFNetworking and Alamofire). It also works for every request in a UIWebview.

Limitations

Downloaded files will be completely in memory before they are written to disk. Because of this large files will not be cached. The maximum file size can be influenced by setting the MAX_FILE_SIZE in the EVURLCache.swift

Usage

Just put the folowing code in your AppDelegate.swift

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    EVURLCache.LOGGING = true // We want to see all caching actions
    EVURLCache.MAX_FILE_SIZE = 26 // We want more than the default: 2^26 = 64MB
    EVURLCache.MAX_CACHE_SIZE = 30 // We want more than the default: 2^30 = 1GB
    EVURLCache.activate()
    return true
}

Debugging

If you are having problems setting EVURLCache up, then enable logging. You can do that by setting EVURLCache.logging = true When reporting an issue, it helps when including this output.

Using EVURLCache in your own App

'EVURLCache' is now available through the dependency manager CocoaPods. You do have to use cocoapods version 0.36 or later. At this moment this can be installed by executing:

[sudo] gem install cocoapods

If you have installed cocoapods version 0.36 or later, then you can just add EVURLCache to your workspace by adding the folowing 2 lines to your Podfile:

use_frameworks!
pod "EVURLCache"

Version 0.36 or later of cocoapods will make a dynamic framework of all the pods that you use. Because of that it's only supported in iOS 8.0 or later. When using a framework, you also have to add an import at the top of your swift file like this:

import EVURLCache

If you want support for older versions than iOS 8.0, then you can also just copy the EVURLCache.swift plus the ReachabilitySwift.swift to your app.

Building the EVURLCache demo

  1. Clone the repo to a working directory

  2. CocoaPods is used to manage dependencies. Pods are setup easily and are distributed via a ruby gem. Follow the simple instructions on the website to setup. After setup, run the following command from the toplevel directory of EVURLCache to download the dependencies for EVURLCache:

pod install
  1. Open the EVURLCache.xcworkspace in Xcode and run the app.

License

EVURLCache is available under the MIT 3 license. See the LICENSE file for more info.

My other libraries:

Also see my other open source iOS libraries:

  • EVReflection - Reflection based (Dictionary, CKRecord, JSON and XML) object mapping with extensions for Alamofire and Moya with RxSwift or ReactiveSwift
  • EVCloudKitDao - Simplified access to Apple's CloudKit
  • EVFaceTracker - Calculate the distance and angle of your device with regards to your face in order to simulate a 3D effect
  • EVURLCache - a NSURLCache subclass for handling all web requests that use NSURLReques
  • AlamofireOauth2 - A swift implementation of OAuth2 using Alamofire
  • EVWordPressAPI - Swift Implementation of the WordPress (Jetpack) API using AlamofireOauth2, AlomofireJsonToObjects and EVReflection (work in progress)
  • PassportScanner - Scan the MRZ code of a passport and extract the firstname, lastname, passport number, nationality, date of birth, expiration date and personal numer.
  • AttributedTextView - Easiest way to create an attributed UITextView with support for multiple links (url, hashtags, mentions).
Comments
  • Cache not found, wrong path

    Cache not found, wrong path

    the file is cached here:

    /var/mobile/Containers/Data/Application/50B1343F-AE81-41BE-A7DB-CA21A059481A/Documents/Cache/192.168.1.224/polymer/bower_components/webcomponentsjs/webcomponents-lite.min.js

    but then it is loaded from here.. and of course not found

    /var/containers/Bundle/Application/78A9AE26-66AA-4264-91AF-CA96DCDBD9EE/TopEase%20Mobile%20App.app/PreCache/192.168.1.224/polymer/bower_components/webcomponentsjs/webcomponents-lite.min.js why its looking in the wrong path?

    fixed? 
    opened by pc11000 17
  • obj-c version does not load the page after cached

    obj-c version does not load the page after cached

    Hi, Sorry to bug you with this old version, I hope there is a quick fix for it. I could load the first time your webpage, then after killing the app, either when its offline or when its online it doesn't load any webpages. Whatever URL I try to load the debug says cache found for URL, it prints the Reachability flag, the age and it stays blank. Any ideas?

    Thanks a lot Greg

    opened by Greg767 17
  • some kind of cached file can't be handled correctly by UIWebView

    some kind of cached file can't be handled correctly by UIWebView

    I've been trying EVURLCache to cache a html5 game(http://game.zorropk.com/gamenow/xiao5haiyanglixianji/) in iOS, but some kind of cached file can't be handled correctly, such as json, plist, fnt and tmx file, the UIWebView will be just black and showed noting. If i change the code to skip caching these kind of files, the game will run properly.

    opened by flycjh 11
  • Google Places Autocomplete not working

    Google Places Autocomplete not working

    Google Places SDK ver. 3.3.0(4.5) autocomplete is not working when using EVURLCache. Requests are being written to cache, and autocomplete seems not to like it, in simply doesn't return any search results. Looking for options to disable caching for Google Places.

    opened by schmidt9 9
  • Add Cache-Control expiration if server header is not set

    Add Cache-Control expiration if server header is not set

    Hi,

    i am trying to modify the header of the response. and i was looking inside the library maybe there was a way to add an option to Modify or add a Cache-Control header?

    if !EVURLCache.ADD_CACHE_CONTROL {
        if let httpResponse = cachedResponse.response as? HTTPURLResponse {
            var headers = httpResponse.allHeaderFields as? [String : String]
            headers!["Cache-Control"] = "max-age=\(EVURLCache.CACHE_EXPIRATION_SECONDS)"
        }
    }
    
    opened by alexookah 9
  • PRECACHE not found

    PRECACHE not found

    Hi there Edwin, this isn't exactly an issue since I'm sure the problem lies with me somewhere. Reading through your existing answers I've seen that you've given friendly replies even to quite rough requests. Therefore I dare ask for your opinion.

    I'm trying to write a tutorial for how to cache a privacy policy locally, which your implementation seems to be perfectly suited for. I've recreated your structure for a PreCache folder in the root, then iubenda.com/privacy-policy folder and finally the 8051057 file in the folder (saved as html).

    EVURLCache.swift(123) cachedResponse(for:): PRECACHE not found /var/mobile/Containers/Data/Application/7C2EBF0D-5F1E-40B9-86E0-7DFFCF5240DE/Documents/Cache/www.iubenda.com/privacy-policy/8051057/index.html

    05/11/2017 22:37:15:088 App name)[9016:.] EVURLCache.swift(126) cachedResponse(for:): CACHE not found /var/containers/Bundle/Application/2F199D2F-8228-48CD-8896-EFDD321AC0C4/App name.app/PreCache/www.iubenda.com/privacy-policy/8051057/index.html

    Where am I going wrong? Thanks a bunch :)

    update: running it again an hour later it gives me:

    "CACHE not rewriting stored file" and returns a white page. I think that's is progress. I now only need to find the reason for it returning a white page both off- and online. Also I found almost an identical posting here when googling for CACHE not rewriting stored file. Sorry about that.

    fixed? 
    opened by s2imon 8
  • Files placed in PreCache are not found

    Files placed in PreCache are not found

    I've tried both in a custom application as well as running the example application right away. Added another folder to the app without any luck as well.

    Not sure if this is a EVURLCache problem rather than something else but writing and reading from the cache folder works.

    The top folder is named according to the domain name convention. When I try in the simulator and later opens the PreCache folder, the files are there. But the PreCache folder cannot be accessed.

    fixed? 
    opened by superoul 7
  • caching html file

    caching html file

    Hi, I find the library very useful, but just have one issue. It doesn't seem to be caching the .html file, is this possible, do I need to switch on a parameter, etc.. The file size of the html is 3.4Kb so its not big at all. I can see it tries to check the precache folder for it, but once it doesnt find it, it just uses the live one. If i disable internet it comes up blank.

    Thanks

    opened by amz4u2nv 7
  • How to prevent EVURLCache to cache a request with Cache-Control header?

    How to prevent EVURLCache to cache a request with Cache-Control header?

    This question comes from someone on Stackoverflow, but we've been having the exact same issue. http://stackoverflow.com/questions/39020639/how-to-prevent-evurlcache-to-cache-a-request-with-cache-control-header

    When I use EVURLCache, the POST request response for my AlamoFire request is also cached even if cache-control and Pragma headers are defined (should be cached only 4 hours in this case).

    It would be great if EVURLCache did actually cache for x hours, like the cache-control header defines, instead of just keeping the old cache.

    fixed? 
    opened by CedricVanAsch 5
  • can't cache

    can't cache

    1.when i open a url :http://m.qiushibaike.com it store,but i cut off wifi can't load the cache data?

    2.the local path is wrong

    2014-10-22 00:40:54.697 LocalCache[5134:119705] EVURLCache.m:(62) CACHE found for /Users/huiyang/Library/Developer/CoreSimulator/Devices/8A37AEBC-49C1-4756-8456-B99345F46A33/data/Containers/Data/Application/218F6749-573A-4898-954A-7AE8B9A92BAF/Documents/Cache//index.html

    //index.html

    opened by xiaoyangh 5
  • EVURLCache and Alamofire

    EVURLCache and Alamofire

    Reported by @nmDejamobile via email.

    Hi,

    I found your EVURLCache lib and it looks nice as it does all the work for me :) But I use Alamofire and I can’t figure out how to get the result of the request. When cache is involed, Alamofire .Success or .Failure callback are not called. However I well see the log stating that the cached data was loaded by EVURLCache. Also, after sometime, Alamofire .Failure is triggered by a timeout.

    Any ideas on how I could use it ? Thanks.

    fixed? 
    opened by evermeer 4
  • Unable to find a specification for 'EVURLCache' when trying to use 'objective-c' branch

    Unable to find a specification for 'EVURLCache' when trying to use 'objective-c' branch

    In Podfile I specify

    pod 'EVURLCache', :git => 'https://github.com/evermeer/EVURLCache.git', :branch => 'objective-c'
    

    but get error message Unable to find a specification for 'EVURLCache'. When I specify another branches (master or Swift2.2) it works

    It actually finds branch but cannot download it for some reason, here is piece of log

    Fetching external sources -> Pre-downloading: EVURLCache from https://github.com/evermeer/EVURLCache.git, branch objective-c $ /usr/local/bin/git ls-remote https://github.com/evermeer/EVURLCache.git objective-c 86a47faacba5a2f4ae856f95cfa249152cb990ff refs/heads/objective-c Git download Git download $ /usr/local/bin/git clone https://github.com/evermeer/EVURLCache.git /var/folders/xf/3rv7br2s35q7v86p3p2dnly00000gp/T/d20210322-29425-i53yak --template= Клонирование в «/var/folders/xf/3rv7br2s35q7v86p3p2dnly00000gp/T/d20210322-29425-i53yak»… $ /usr/local/bin/git -C /var/folders/xf/3rv7br2s35q7v86p3p2dnly00000gp/T/d20210322-29425-i53yak checkout --quiet 86a47faacba5a2f4ae856f95cfa249152cb990ff [!] Unable to find a specification for 'EVURLCache'.

    opened by schmidt9 0
  • Cache not updating

    Cache not updating

    I'm unable to get the module working at all, at this point. I was previously able to load the 'live' site, the module would cache, and I could copy the cache over to precache. However, evurlcache never pulls the live site and always loads from precache.

    If I remove the domain folder out of the precache folder, it loads the 'live' site but does not save it to cache. I have tried uninstalling the app, etc.

    It seems like the callback to attempt a load and cache a live site is never initiated. However, it seems to randomly cache various parts of random pages, but never the entire page. This includes the sample links provided.

    I'm fairly desperate for a solution and have attempted stepping through the code, but I can't find anything glaringly obvious. I also haven't delved too much into documentation regarding NSURLCache.

    Does anyone have a working example or a suggestion? I've been struggling with this for a while and unfortunately I don't have another solution readily available.

    opened by rtnlsltn 0
  • Cache is not updating

    Cache is not updating

    Downloading a URL and all folders created in cache. Trying to hit the same url after some update in the content .In that case timestamp is changing but content inside file is not changing.

    opened by pradeepispv 0
  • Question: How to force reload request and expire existing cache?

    Question: How to force reload request and expire existing cache?

    Hi, i am using this in my app and i would like to know how can i force reload a request to skip any existing caches and update the content view with the latest content?

    question fixed? 
    opened by alexookah 9
  • Some web pages cant be opened in webView after caching - redirect issue

    Some web pages cant be opened in webView after caching - redirect issue

    Try to load demo demo app with webView with any of links below instead of "http://evict.nl":

    http://www.newser.com/story/229485/aetna-doing-something-about-workers-student-loans.html http://www.beckershospitalreview.com/payer-issues/when-the-doctor-orders-time-in-the-park-humana-metcare-partner-for-nature-driven-prescriptions.html http://www.beckershospitalreview.com/healthcare-information-technology/10-largest-hipaa-settlement-fines.html

    After this turn off internet connection and open app again. Expected result: web page is loaded from cache and displayed Actual result: web page is failed to be opened

    Same behaviour appears for some other urls but not for all.

    enhancement Help needed! 
    opened by ChristRm 8
Releases(3.6.0)
Owner
Edwin Vermeer
Edwin Vermeer
a NSURLCache subclass for handling all web requests that use NSURLRequest

EVURLCache What is this? This is a NSURLCache subclass for handeling all web requests that use NSURLRequest. (This includes UIWebView) The EVURLCache

Edwin Vermeer 296 Dec 18, 2022
Wrapper class for handling all tasks related to RSA cryptography

RSAWrapper Wrapper class for handling all tasks related to RSA cryptography USAG

null 1 Dec 24, 2021
Easy to use CFNetwork wrapper for HTTP requests, Objective-C, Mac OS X and iPhone

ASIHTTPRequest is an easy to use wrapper around the CFNetwork API that makes some of the more tedious aspects of communicating with web servers easier

Ben Copsey 5.8k Dec 14, 2022
An auto-layout base UITextView subclass which automatically grows with user input and can be constrained by maximal and minimal height - all without a single line of code

Deprecated This library is no longer maintained and is deprecated. The repository might be removed at any point in the future. MBAutoGrowingTextView A

Matej Balantič 125 Jan 13, 2022
An original project making use of custom UITableViewCells, date formatting, json parsing, and handling user location.

SunTimes An original project making use of custom UITableViewCells, date formatting, json parsing, date and time formatting based on the json data, an

David Chester 0 Feb 8, 2022
Xcode-developer-disk-image-all-platforms - A repo which shares all developer disk images for iOS, tvOS, watchOS

Disclaimer: The available resources and files from this repo are uploaded from many contributors. The files are unverified, untested, and could have n

Hai K 253 Dec 21, 2022
An easy to use UITableViewCell subclass that allows to display swippable buttons with a variety of transitions.

MGSwipeTableCell MGSwipeTableCell is an easy to use UITableViewCell subclass that allows to display swipeable buttons with a variety of transitions. T

Imanol Fernandez 7k Dec 26, 2022
An easy-to-use UITableViewCell subclass that implements a swippable content view which exposes utility buttons (similar to iOS 7 Mail Application)

SWTableViewCell An easy-to-use UITableViewCell subclass that implements a swipeable content view which exposes utility buttons (similar to iOS 7 Mail

Christopher Wendel 7.2k Dec 31, 2022
🌸 Powerful Codable API requests builder and manager for iOS.

This lib is about network requests with blackjack, roulette and craps! Using it you will be able to convert your massive API layer code into an awesom

CodyFire 251 Jan 8, 2023
Thin wrapper around NSURLSession in swift. Simplifies HTTP requests.

SwiftHTTP SwiftHTTP is a thin wrapper around NSURLSession in Swift to simplify HTTP requests. Features Convenient Closure APIs Simple Queue Support Pa

Dalton 1.9k Dec 7, 2022
Stub your network requests easily! Test your apps with fake network data and custom response time, response code and headers!

OHHTTPStubs OHHTTPStubs is a library designed to stub your network requests very easily. It can help you: test your apps with fake network data (stubb

Olivier Halligon 4.9k Dec 29, 2022
Mock Alamofire and URLSession requests without touching your code implementation

Mocker is a library written in Swift which makes it possible to mock data requests using a custom URLProtocol. Features Requirements Usage Activating

WeTransfer 898 Dec 26, 2022
An elegant library for stubbing HTTP requests with ease in Swift

Mockingjay An elegant library for stubbing HTTP requests in Swift, allowing you to stub any HTTP/HTTPS using NSURLConnection or NSURLSession. That inc

Kyle Fuller 1.5k Dec 3, 2022
Swift AWS Lambda to automatically assign engineers to pull requests with a Slack integration

PR Assigner A Swift AWS Lambda to automatically assign engineers to pull requests with a Slack integration. Features ??

Just Eat 28 Oct 18, 2022
Automatic testing of your Pull Requests on GitHub and BitBucket using Xcode Server. Keep your team productive and safe. Get up and running in minutes. @buildasaur

Buildasaur Automatic testing of your Pull Requests on GitHub and BitBucket using Xcode Server. Keep your team productive and safe. Get up and running

Buildasaurs 774 Dec 11, 2022
🚀 Access my pull requests from the menu bar

OhMyPullRequests ?? Access my pull requests from menu bar. It lists pull requests that either: Someone requests you to review the pull request. Your p

Zihua Li 29 Jul 2, 2022
Example project guide you schedules multiple thread for network requests in RxSwift, which is optimize your app's performance better.

RxSwift-Multi-Threading-Example Example project guide you schedules multiple thread for network requests in RxSwift, which is optimize your app's perf

Huy Trinh Duc 6 Nov 4, 2022
a iOS network debug library, monitor HTTP requests

NetworkEye README 中文 NetworkEye,a iOS network debug library,monitor HTTP requests. It can be detected HTTP request include web pages, NSURLConnection,

coderyi 1.4k Dec 31, 2022
Domain Specific Language to safely build predicates and requests to fetch a CoreData store

SafeFetching This library offers a DSL (Domain Specific Language) to safely build predicates and requests to fetch a CoreData store. Also a wrapper ar

Alexis Bridoux 13 Sep 13, 2022
Synchronous requests for AFNetworking 1.x, 2.x, and 3.x

AFNetworking-Synchronous A minimal category which extends AFNetworking to support synchronous requests. Usage 3.x pod 'AFNetworking', '~> 3.0' pod

Paul Melnikow 160 Dec 7, 2022