How to create offline webapps on the iPhone
Recently Google launched their latest mobile version of Gmail optimised for iPhone and Android based browsers. One of the features that stood out was the offline access thanks to the browsers support of html5 application cache.
Documentation on the application cache feature supported in safari iPhone 2.1+ is scarce and of that documentation it doesn’t go into great detail. The best place to learn about this is on the Safari DevCenter under the mobile section, there it has 2 documents introducing the user to offline webapps; the first is a quick rundown on just the manifest file and the second article touches on a few more features available to offline webapps such as the javascript events for updating the cache when the user is online. We’ll delve into these later in the article but first let’s take a look at a working example.
To see the offline webapp in action, load the demo on your iPhone, then turn Airplane Mode on, re-open Safari and reload the demo. This time it will fetch the files from the cache that was created on the initial load.
How does it all work?
To get a basic offline webapp up and running is incredibly simple but it does have one caveat which tends to get a lot of people frustrated quickly when for some reason the offline feature isn’t working. We’ll explain that issue shortly.
The first thing we need to do is create what is called a cache manifest file which has references to all the resources we want to save. Whether it be JavaScript, CSS, images or html, below we can view the manifest file used in the demo.
CACHE MANIFEST # Offline cache v1 # html files article.html # css files assets/_styles.css # js files assets/_javascript.js # images assets/ico_ninja-star.gif
The manifest file is a simple plain text file that holds the file names you wish to cache, the paths are relevant to where you saved the manifest file which is recommended to be in the root of the site. This file will be saved as filename.manifest, where filename is anything you wish. Lines that start with a # are comments and are ignored by the cache.
Referencing the cache file
We now have our cache manifest file setup and named, the next thing we need to do is reference that file in the html so this offline access will function for the specified files in the manifest.
<html manifest="thecssninja.manifest">The manifest file is referenced in the html tag through the manifest attribute and just points to the filename.
Now the one issue that catches a lot of people when trying this out is not setting up the mime type correctly in their chosen web server. Whether it be IIS, Apache or something else, you’ll need to make sure that the .manifest file is fed through as text/cache-manifest. For example in IIS the .manifest mime type is actually already declared to serve .manifest files as application/x-ms-manifest for offline webapps to work this will need to be changed to mime type text/cache-manifest.
For Apache you can add the text/cache-manifest to the mime.types file found in the conf folder in apache and add the following to the bottom of the file.
# html 5 application cache - offline access text/cache-manifest manifest
For IIS open up the IIS manager found in Control Panel > Administrative Tools > Internet Information Services double click the Mime Types icon in the manager and scroll down the list until you find the .manifest file and edit the mime type to have text/cache-manifest.

That’s it, to get a basic offline webapp to work is incredibly simple all it takes is the manifest file to specify which files to cache, declare it in on the <html> tag using the manifest attribute and you have yourself a site still accessible even if the user has no network connection.
UPDATE: GeoNomad in the comments suggested a great tool to make sure your manifest file is being fed through with the correct mime type, Web Sniffer. I put my manifest file through the Web Sniffer tool, you can see that the Content-Type is set as text/cache-manifest.
Updating the cache
If you want to update the cache you either need to change/add file references to the manifest and then tell the cache to update. Updating a file that the manifest calls will not make the cache reflect the changes. The mozilla developer article on applicationCache makes a good suggestion to version your manifest file as the JavaScript events described below will only fire if there is a change to the manifest file. To update the cache we have:
window.applicationCache;This object has various stages depending on what the cache is doing which can be checked by using the .status method. There are 6 different stages:
- Status 0 (UNCACHED) is returned which means that there is no cache available
- Status 1 (IDLE) is returned means the cache you have is currently the most up-to-date
- Status 2 (CHECKING) is returned means there is a change in your manifest file and it is checking it for changes
- Status 3 (DOWNLOADING) is retuned means changes have been found and they are being added to your cache
- Status 4 (UPDATEREADY) is retuned means your new cache is ready to be updated and override your current cache
- Status 5 (OBSOLETE) is returned means your cache is no longer valid meaning it has been removed
These available statuses can be attached to the applicationCache object with event listeners so we can tell the web app what to do on what status. In our case we want to update the cache to reflect changes we have done.
var webappCache = window.applicationCache; function updateCache() { webappCache.swapCache(); } webappCache.addEventListener("updateready", updateCache, false);
In the above example we attach an event listener to the applicationCache looking for the updateready status which means there is a change to the manifest file and our cache is ready to be updated we do so by using the swapCache() method.
There is 2 more event handlers which do not appear in the window.applicationCache.status these are part of the event summary. Those are error & progress. We’ll take a look at how to use the error event, the progress event is basically the same as the downloading event handler.
var webappCache = window.applicationCache; function errorCache() { alert("Cache failed to update"); } webappCache.addEventListener("error", errorCache, false);
All the error event handler does is return the specified function we attached in the event listener when the cache is not available or does not exist.
Event summary
In the applicationCache we have various events available so when the cache is being updated, or as mentioned above when something goes wrong. We can attach to those events and keep the user informed on what is happening. These events will execute in specific order based on what is happening with the cache and therefore give us useful hooks to represent that back to the user.
Pete who commented below and needed a way of indicating to the user that the cache was downloading prompted me to look further into the events that get fired and which ones would be useful in this scenario. I created a demo which will indicate to the user that the cache is downloading by showing a loading icon and once the cache had finished downloading, the loader would be hidden.
The event order for this example was as follows:
- checking – The page loads and the cache is checked for any changes.
- progress – The download event actually gets fired before this but we don’t need to hook into that. The progress event will fire for each file that is referenced in your manifest until the cache has finished downloading.
- cached – The cache has successfully downloaded and the cached event is fired so we utilise that to hide the loader.
- updateready – This event is fired so we can then swap the old cache with the newly downloaded one.
In the above mentioned demo we also attached event listeners to the error and noupdate events so we can handle errors and if the cache is already up-to-date.
Is the user online
There is also a new method on the navigator object called onLine which returns a boolean value if there is a network connection or not.
navigator.onLineIn the article example the onLine method is used to update the title if the user is on/offline.
Only the beginning
The applicationCache is not yet finalised and is of course subject to change with newer and refined features. I’m sure there will be additions in the upcoming iPhone OS 3.0 release. If there are updates unfortunately these cannot be discussed until the NDA is lifted. But of course this won’t stop us speculating.
Some of the features available in applicationCache on firefox 3.1 and safari 4 will inevitably be added in future releases of the iPhone OS. Such as the NETWORK: and FALLBACK: sections in the manifest file, these allow for the developer to specify a file they wish to never cache or to have a file load if something fails with the first option.
Post filed under: css, javascript, xhtml.
Very interesting … but is there a limit as to what can be cached? Just tried based on your model, total site is 5 mb size with hundreds of small files (4 – 15 kb). It just will not cache, while your sample on the same server performs well.
cheers
pete, June 17th, 2009No I haven’t come across a size limit nor have I found any references anywhere to indicate that there would be a size limit. One thing that did stop my web app from caching was misspelling file name in the manifest, have you made sure your manifest hasn’t got any spelling mistakes? A good way to debug any issues is to attach an event listener to the error event and see if it’s failing the cache, you can also check the status of the applicationCache and see what it’s returning. Take a look at the JavaScript file I’m using for the example it has a switch statement in their and logs useful messages to the browser console to see what the status is.
The Css Ninja, June 18th, 2009Hi, I learned last night that the current cache limit for webapps is supposed to be 5mb. I reduced some stuff, so that took care of one thing.
My true problem seems to be, when I go into a hierarchy. All links straight off the index.html page work perfectly well, but when I do the following, safari on the iPhone (not on the mac) crashes gloriously:
FILE: my.manifest
Content:
CASH MANIFEST
this.css
that.js
Vegetables/AtoZ.html
Vegetables/Spinach.html
Vegetables/Chickpeas.html
FILE: index.html
Links to:
Vegetables/AtoZ.html
Vegetables/Spinach.html
Vegetables/Chickpeas.html
Offline all three links work fine, however:
When I tap on Vegetables/AtoZ.html and from within there want to get to the Spinach or Chickpea file Safari iPhone crashes.
It is as if there was an undocumented “it only works on the the first hierarchy level”.
Have you tried a second or third level hierarchy with manifest yet? Be interested to hear from down under.
Cheers
pete, June 19th, 2009Just quoting your email so the comments make sense.
So your saying you are just referencing all the files directly and not listing their folders names before and that caches all of them? Can you provide a link to a test version that crashes the browser and one that works?
You could in theory attach to the downloading event handler for the cache webappCache.addEventListener(“downloading”, promptUser, false); which would call a prompt to ask a user if they would like to cache the site. Then depending on their answer either continue or throw an exception.
The Css Ninja, June 19th, 2009I have a question on the applicationCache status, having copied your js sample:
Changing a file and changing the manifest I get Status 2 (checking) in an alert box which I place at the top:
Afterwards the newly modified file is being displayed.
At which point can I get in with an alert box to actually confirm that the cache has indeed been updated?
I tried the following, but none of the desired alert boxes trigger:
BTW: The hierarchical problem seems to be solved. Somebody else looked into it and it might have been, because the manifest contained files which did not exist anymore. Preciser analysis in a few days.
pete, June 23rd, 2009That will always return false, what you need to do is attach an event listener to the status itself. Status code 2 will always return first if there is a change to the manifest, followed by downloading and updateready. Just do the following:
This will fire the updateCache() function and alert you that the cache has been updated.
Yep same issue I had when doing the demo, although I misspelt my file names therefore it was looking for files that didn’t exist.
The Css Ninja, June 24th, 2009Okay.
You Ninja. Me not even a half boiled rice corn.
Will this give me the right message upon update?
Lol, we’ve all got to start somewhere.
Your code looks fine only change I would make is removing the if statement in your updateCache method as that only gets fired when the updateready status is passed to listener which is already status 4 so no need to check for it again. Your onload event listener doesn’t need to be there if your not calling anything after load.
The Css Ninja, June 25th, 2009tks a lot. and now an off-topic one: the app works fine when i run it on my local server and pick it up with the iphone as part of the local network. the moment i upload the whole thing to the external providers place no caching happens. i am told it was “bad formatting” of the manifest file and that the provider reformatted it, but nothing changes the non-workability of caching on the distant server. what could be the right debug procedure? .. email me privately, if you wish.
pete, June 27th, 2009Have you set up the .manifest extension to be fed through as text/cache-manifest in your mime types on the server your uploading to? If it’s working on your local there should be no problem with your manifest file.
The Css Ninja, June 27th, 2009on the external one the declaration is in an htaccess file.
pete, June 27th, 2009I did have trouble setting the mime type through my htaccess file on my hosting, I ended up setting the mime type through my admin control panel. Just do a check for the applicationCache status to see what it’s returning on your server, if you get 0 it would most likely mean the mime type isn’t setup correctly on the server.
The Css Ninja, June 27th, 2009problem sorted. cause: reference in an html file to a css class which was no longer defined …. would you like a little js-contract? need a progress indicator during download so people know it is happening and do not interrupt too early (as downloads are approx. 4mb).
pete, July 5th, 2009If you need to indicate that something is happening I would show an animated gif icon and display it when the cache is downloading, then use the updateready event to hide once the download is done e.g.
This won’t give you exact progress, but it will indicate to the user that something is happening and if you position a container over the top of the site with the animated gif this will stop the user from doing anything until it’s loaded.
The Css Ninja, July 5th, 2009I implemented this and it works amazingly well, in Safari. But what I really want is for it to work with UIWebView, and it doesn’t seem to be doing that – does anyone have any idea on putting the two together? Any success stories?
Gavril, July 10th, 2009Just got a brand new 3GS and trying to get some off-line webapps going. I’ve been having some trouble with mine not working offline and just tried yours with the same results.
Mark, July 12th, 2009I notice through using a proxy that the phone is never requesting the “manifest” file. Seems like a bug in the phone?
What versions have you had this working on?
@Gavril – I dont see why it wouldn’t work in a native app as it would essentially be calling an instance if safari in your app. I’d be interested to know if you find the solution.
@Mark – That’s strange I have the 3GS also and it’s working fine. Try enabling the debug bar in safari, the demo logs messages to the console it should let you know if something has gone wrong.
The Css Ninja, July 12th, 2009So I try to get the anim.gif to run by doing this:
After that one I have this:
The log file gives me the protocol “Downloading” but does not show the page i create to show the anim.gif
and also I get this javascript error message:
an error for line “webappcache.swapCache()” -> INVALID_STATE_ERR: DOM Exception 11
Bit stuck now. Still half-boiled rice corn.
pete, July 14th, 2009Why are you trying to open a new window? I put together a quick demo that simulates lots of content being cached. It will show a loading icon when the downloading status is passed to the applicationCache when the cache has finished downloading and the updateready status is returned the loading icon will be hidden. I delayed the hiding of the loading icon for 2 seconds using a setTimeout, for your implementation I would just do the hiding in the updateCache function.
The Css Ninja, July 15th, 2009Learning, master, learning … I thought I need to open a window so I can close the thing again afterwards. Obviously that is not the case, so I’ll have to learn how to do that. — In the demo, thank you very much indeed for your time, the icon does not disappear however. It runs and runs and runs.
pete, July 15th, 2009Ok so the demo should work as expected now, thanks to your scenario I have discovered quite a few more useful bits of information. I’m going to update the article in the coming days and shed some more light on those discoveries.
The Css Ninja, July 16th, 2009Wonderful! The demo works in showing the gif.
Now where would I go and look for a mistake I made, when in the next step in the line
“webappCache.swapCache();”
I get this error message: INVALID_STATE_ERR: DOM Exception 11
pete, July 20th, 2009Can’t really say without actually looking at the site. Based on the W3C explanation of the exception.
Looks like you’re potentially trying to access webappCache object outside of it’s current scope.
The Css Ninja, July 20th, 2009[...] research into offline capabilities. HTML 5 offers some exciting new capabilities in this area. Here’s a great article on how to take advantage of offline access to content in HTML [...]
Going Offline with HTML5 | PointAbout: Mobilize Your Brand, July 22nd, 2009Seem to have solved the EXCEPTION 11 error:
I deleted under
function updateCache() {
this:
webappCache.swapCache();
… and inserted
loader.display = “none”;
… plus an alert box to advise the user that the update has been completed.
The modified files have obviously been downloaded to the iPhone cache and the app works. No “swapCache” required. — This is good, but what exactly happened?
PS: Is the gif your copyright or public domain?
pete, July 28th, 2009Hmm the swapCache() method is what changes over the current cache with the updated cache. Removing that will never update the cache, even though it has detected a changed, downloaded it and fired the alert to inform the user that this has happened without swapCache all of that work will be for nothing. If you reload it will load the old cache as the new cache was never swapped.
The gif was generated from ajaxload.info just generate your own one there to better suit your web app design.
The Css Ninja, July 28th, 2009Well that IS the strange thing: SwapCache() is off, after the update and subsequent turning on of flight mode on the iPhone all changed files appear as changed, all other files can be called without problems. — Really strange. As if progresscache was performing an immediate caching.
pete, July 28th, 2009Ah but that’s the issue, SwapCache is only called if the user already has a cache. If there is an update SwapCache will swap the old cache with the newly downloaded one. If you try to push out an update to one of your cache files all the events will fire and it will act like it’s downloading a new cache but without the final SwapCache method in the onupdateready event it will never change over and the user will be stuck with the original.
The Css Ninja, July 29th, 2009UPDATED: Updated article to reflect some of the ideas expressed in the comments.
The Css Ninja, August 1st, 2009There still seems to be one problem somewhere along the line with “some” users.
While 4 testers have no problems updating, one tester with an up to date (3.0) iphone 3G reports that the update messages goes on and on and on. He finally escapes the scene, restarts the iPhone and everything appears to have been updated. — This is something we talked about before. It is a hangup at the swapcache point.
The javascript call now comes at the end of the html file (just before ) so the loader div is before it.
So it works almost as it should, but this one tester gives me a mystery, and as I had the same phenomenon before I just wonder what is not known about updatecache which could cause this.
As a separate note: Your in-depth insight into these new features and your helpfulness is very much appreciated on this side of the globe. Thanks.
pete, August 1st, 2009Hi, I’m probably the noob-iest one here, but I’m trying to make my soundboard web app work while offline. I haven’t gotten it to work with my 50+ images, but I’m willing to pursue it once I’m sure that it can cache mp3 files. Is MobileSafari capable of caching mp3s specified in the manifest?
Thanks for all your help, your site has been a great resource!
Harry Shamansky, August 19th, 2009I believe based on previous comments there is a size limit of 5mb, though this is unconfirmed. If your total assets are higher than that it may not cache or will return an error. You should be able to cache any file regardless of format, it will depend more on the file size than type.
You’re very welcome, thanks for reading.
The Css Ninja, August 19th, 2009That makes sense, though I’ve also heard that the user is prompted if the cache is over 5mb.
On an unrelated note, there isn’t a way to play a short sound without the full screen player opening in a web app, right? It’s not a big deal, as it opens and closes pretty quickly, but it still would be great if there were an alternative.
Harry Shamansky, August 19th, 2009I’m not sure if the iPhone prompts the user for more space, I know the desktop does.
Yeah audio and video on the iPhone will only play through the fullscreen player no way around it.
The Css Ninja, August 19th, 2009This is great stuff!
Josh, August 20th, 2009I got this working perfectly in the regular browser but have had no success getting it to work within a UIWebView. It returns Status 0 all the time within the view.
If you or anyone has had any luck please let me know! Thanks for the great write up.
Yeah a few people have mention not being able to get it working in UIWebView which is strange. Will keep you posted if I find out anything.
The Css Ninja, August 21st, 2009Hi there,
I’m trying to set this Cache thing up and I can’t seem to make it work.
I made the cache.manifest file and it’s correct.
I added the MIME type in my mime.conf file (Apache locally installed on my iMac).
I load the app from Safari on the iPhone, save it on my homescreen. But everytime I load it up, i get the spinner in the status bar RELOADING everything.
It’s not a matter of life and death right now, as I can run the “App” locally instaled on the iPhone through SSH, but it would be cool to cache everything on the phone.
Alex Buga, September 2nd, 2009Hi Alex,
Have you attached the various events to your applicationCache object to see if you are getting an error in the caching. Make sure in your cache file that there are no misspelt assets or non existent references in there otherwise it won’t cache.
The Css Ninja, September 2nd, 2009Hi Ninja,
Robert Selldorf, September 2nd, 2009do you have any news about the UIWebView not working with this method?
Hi Robert,
I did post on a thread in the Apple developer forums asking why the appCache wouldn’t work in UIWebView and it doesn’t look good. I haven’t got official word from an Apple employee, but from what people are saying it’s not supported.
The Css Ninja, September 2nd, 2009hi!
1- I have a problem with your demo, with firefox 3.5.. when I reload the page, i get ”
Content Encoding Error
The page you are trying to view cannot be shown because it uses an invalid or unsupported form of compression.
2- I just created a manifest file on my website. The firefox preference menu show “mysite” in the list of cached sites… Does it mean the mime type is set?
it’s 0bytes, though
thanks cssninja!
yvan, September 6th, 2009edit : answer for #2 – the mimetype wasnt set but I could edit .htaccess
yvan, September 7th, 2009Is that an issue with the demo I’m hosting on my site or is it the demo files you have downloaded? I’m using FF 3.5.2 and I don’t get that error, I do however get a JavaScript error because of the google analytics in the page but that doesn’t stop the page from caching.
The Css Ninja, September 7th, 2009I have had no problem creating offline apps this way, but I have a problem getting rid of them.
If I delete the icon from the screen and then access the same URL in safari, it starts to load and then crashes. (OS 2.2).
I have tried resetting the iPod but the crash persists. Clearly something remains in safari that tells it to look in the now non-existent cache.
I have tried clearing the History, but no joy.
Is there any advice on how to remove offline apps properly once you have created them?
TIA
GeoNomad, September 8th, 2009Since this thread is still current, I think it’s worth mentioning that Dashcode *3.0* (it comes with Snow Leopard when you install XCode) has an option to “make your webapp available offline”
It basically does all the caching work for you. I have yet to see whether it works for me, but I’ll find out soon.
Harry Shamansky, September 8th, 2009Just so you’re aware you don’t need to add the website to your home screen for the cache to work.
To clear your cache close the window in safari then quit the app go to Settings > Safari > Clear Cache, that should kill off the cache. Crashing seems a bit extreme it should throw an exception if the cache is invalid or non-existent. Perhaps that is a bug in 2.2?
The Css Ninja, September 8th, 2009That’s great news, I imagine it would purely create a manifest file which references all your assets.
Would be interesting to know if it attaches any listeners for you to do things like progress etc.
The Css Ninja, September 8th, 2009Well, it’s still very basic. Dashcode won’t even show you or let you edit the manifest file until after you’ve saved to disk or exported. Less room for error this way, I suppose.
Harry Shamansky, September 8th, 2009Clearing the cache did the trick. In fact I thought of it during the night and did it this morning before I came back here. Don’t know why I didn’t try that before.
I think it did throw an exception. For a brief second there was an Error Message bar, but Safari crashed before I could read it. Been too lazy to look in the crash log to see if there was anything relevant. Maybe I will later.
Yes, I had noticed that the cached version is used even if you type the URL offline, so there is benefit and danger to using the manifest without paying attention.
Thanks.
GeoNomad, September 8th, 2009If the only way to really remove an offline web application is to clear the cache, that means that all offline web apps will also be removed.
Is there really no way to remove a single app?
This seems like a serious problem. I already have several offline webapps on my iPod and expect many more.
GeoNomad, September 9th, 2009It’s still not right that the browser would crash just because there is an error.
Unfortunately clearing the cache is an all or nothing process, much like resetting the location services does it for every single app rather than individually. Seems they should really make it work like the notifications does.
Even with finer control over cache clearing it would still be at the app level and not the individual cached site level.
If the cache returns a 404 or 410 the obsolete event is fired and the browser will naturally delete the cache, that could be an alternative to going through the menu?
The Css Ninja, September 9th, 2009After a few hours of bug fixing I got mine running except for one thing. I like to cache some .mov files. I kept it all under 5 MB, but in Mobile Safari it gives me a “broken” play button. It works fine in firefox for example. I can’t find it anywhere on the web, but I think the native iPhone players do not use the files stored by Safari and look for the online files, right?
Matthijs, September 9th, 2009I’m not entirely sure what you mean? Is the cache not working on .mov files?
The Css Ninja, September 10th, 2009Just an update to everyone, I got official word from an Apple employee that the applicationCache is not supported in the UIWebView. But they did recommend another forum post that shows you how to have a website run locally using a different technique, in short put your files in the Resources folder http://retromaccast.ning.com/profiles/blogs/iphone-programming-for-apple
The Css Ninja, September 10th, 2009What I mean is the .mov file is cached by the browser (at least that is the case on a regular browser as I can play the movie while offline) but when I want to play the movie by clicking a link in the cached html files on the iPhone, the native application for video playback will open and I think it will look for the file on the original URL and not the file Safari cached.
About the “Resources” solution above. It is quite nice but the great thing about UIWebView is that you do not need to distribute an app.
Matthijs, September 10th, 2009Have you tried using a smaller filesize video, or just the video by itself? Perhaps there is a size limit, this is only speculation.
The Css Ninja, September 10th, 2009The video is just 1.4 MB, so it should not be a problem. In Firefox it is easy to see how much data is in the cache for each domain (firefox>preferences>advanced>network) and there the movie is included. I think only Safari can use the cache and not other programs (like the video player)
Matthijs, September 10th, 2009I wrote last week that your demo, here, crashed my firefox 3.5.2.
I upgraded to 3.5.3 today and it still does… Well.
It might be a bug specific to the linux version.
I’d didn’t dive into this technique yet, so before I do, I’d like to know if the caching speeds up an online web-application with the iphone (dynamic website with a lot of content fetched online)? What’s the best way to do? cache as many files as possible? the javascripts?
yvan, September 11th, 2009That’s a very good point. I’m sure it could be due to the fact that video and audio tags in iPhone Safari don’t act the same way as a desktop browser and would probably bypass the cache. Will investigate further, but good find.
The Css Ninja, September 11th, 2009Must be a bug with the linux version It seems fine on 3.5.3 in Vista & 7.
The whole point of the applicationCache is purely for offline access rather than speeding up the web app. Though it would make the initial visit to the site much snappier as you can cache all the pages before the user will get there. Caching all the static content would definitely speed up the responsiveness, but if you have a lot of assets you wish to cache it can make the first time visit very slow.
The Css Ninja, September 11th, 2009@Matthijs
My recent experience also suggests that embedded video is not possible offline… and that was the whole point of trying to make this small offline app.
I still hold a small flicker of hope… the iphone… no video… doesn’t sound right to me.
I did get the rest of it working offline after some problems… being that the manifest is aggressively cached and after fixing a small problem in it I had to rename it to make offline work at all. That was my biggest caveat.
Martin Westin, October 19th, 2009First thing I tried when I read this was downloading the demo.
It didn’t work on the iPhone, but the original demo did!!!
Is it because of my server?
The demo is on: http://projecten.maxmakes.nl/cache11/index.html
Max
MaxMakes, October 26th, 2009Looking at the console.logs it’s returning a status of uncached, if it was working it would return status checking. It’s also firing the error method so you may want to print whats happening.
Just add error to the error method and log it to the console, do this in Firefox with firebug so you can get more in-depth results.
I would start stripping back items in the manifest and see if that works.
The Css Ninja, October 26th, 2009I tried this but he now said it is an object event.
How can I get the error.
You can see the problem in the example of my previous message.
Thanks for helping me
Max
MaxMakes, October 26th, 2009http://projecten.maxmakes.nl/cache11/thecssninja.manifest
is returning content-type: text/plain so it won’t work.
You can check the headers using this handy tool: http://web-sniffer.net/
FYI, another working example is at http://benlo.com/jaipho – an offline slide show builder.
GeoNomad, October 26th, 2009@GeoNomad – Thanks for the handy tool. Will have to do an update to the article as quite a few people get stuck on setting the right mime type.
The Css Ninja, October 27th, 2009The mime type can be tricky, especially if you don’t have access to the server configuration. But a nice trick is to use a php script to generate the whole file, including the header. Safari is happy with a manifest file such as manifest.php and as the php can generate the content on the fly, life is easy.
Also, the php script can generate a random version number while debugging, so you can just forget about the whole manifest thing. Just remember to load twice every time. If you want a copy of one of my scripts, just email me.
For small webapps, this method means that content is always downloaded when online, and always works offline with the last load. No fuss, no muss.
GeoNomad, October 27th, 2009My company has been working on an issue with UIWebViews and caching and the solution was to build our own caching that reads the manifest.
On a separate issue – I am writing a web app and trying to cache an mp4 file and a pdf. The cache is under 5 megs. It seems the pdfs and the mp4s just will not cache. With pdf’s, it’ll try to go to the URL regardless of cache, and with the mp4, it tells me it can’t play the file. Anyone have a solution or see anything like this?
Mike D, December 5th, 2009Yeah the official word from Apple is that you cannot use applicationCache in UIWebViews.
The reason video/audio/pdf won’t cache is because they are loaded in external applications e.g. HTML5 videos get loaded in the media player and will always pull the source from the server. Same goes for audio and pdf.
The Css Ninja, December 5th, 2009Actually i was able to get a pdf to cache by loading it in a base64 encoded string (data:), but the results were REALLY slow. still, for those who really need it, may be a worthwhile solution – didn’t work for video though.
Mike D, December 5th, 2009You might try serializing with toDataURL and saving to LocalStorage.
GeoNomad, December 5th, 2009Hey does anyone know if its necessary to create a manifest file if you are using Dashcode 3.0 to create a web app for the iPod????
ryan, December 9th, 2009Depends if you are going to want it to work offline, without a manifest file offline will not work. Dashcode 3.0 allows you to tick a box to make a webapp function offline, all that does it creates a manifest file for you listing all your assets. I’m not sure how dashcode allows you to handle errors/events for the applicationCache if at all.
The Css Ninja, December 9th, 2009I have downloaded the sample zip file and after I add an htaccess file it works fine.. However, I can not add images to the small website? I did have everything working for quite sometime and had many images working, yet i keep getting a safari error when i turn off wi-fi on my ipod touch. Please help!
my .htaccess file just contains the text below:
AddType text/cache-manifest .manifest
I am super frustrated as I had everything working, yet now i can not get it to work anymore…..
Stephen, December 14th, 2009Hard to tell without some sort of example or link?
The Css Ninja, December 14th, 2009Here is the project I am working on right now.. But I have changed the manifest file, but even with the manifest file containing all the images it still breaks.. link is here.
http://www.stephencarr.net/ipod/nursing/nursing.html
Stephen, December 15th, 2009You’re image doesn’t exist, http://www.stephencarr.net/ipod/nursing/images/bg_full_screen.png, I get a 404. If you reference files that the cache can’t resolve the offline caching will fail.
The Css Ninja, December 15th, 2009It works NOW!!!! Thank you! You were correct, I was referencing a wrong background image. I corrected that and it still didn’t work, so I simply erased everything off the server just to be sure there weren’t any bad files floating around, and re-uploaded and now we are good to go! That was a pain!! But totally worth it, thanks again man!
Stephen, December 15th, 2009I’ve gotten the app manifest and offline caching working, many thanks for the article! I’m able to bookmark my site/app to the home screen and load it from there. But, once opened from the home screen, certain links will jump out and open in mobile safari – despite the fact that i preventDefault() on all link clicks!
I have an onclick event handler bound at the body level. Using event delegation, it catches any click on any link, looks at its href, and dynamically calls a templating function to update the page. I call preventDefault() on the event object – for *some* of my links this works, and the page is updated with my template. For the links that result in a hit against the local database before outputting the results of the template, the links are opened in mobile safari.
In desktop safari, all the links work even when i’m offline – something is happening that’s mobile safari specific.
Any thoughts on why some links would open offline, but others not? None of the link URLs in question are listed in the manifest file, but they don’t need to be since the link action is prevented
Jo, December 20th, 2009It’s hard to say without seeing exactly what you are doing.
You should check out iUI or jQTouch and see how they handle page loads. I’d imagine they would be hijacking the links like you are but there might be a quirk to get around the issues you’re having.
The Css Ninja, December 20th, 2009what do these links point to? are they all just regular http? some other protocols are not supported in the same manner in full screen mode as they are in mobile safari. Another reason might be your target (if any). Also, AJAX requests are not supported for caching
Mike D, December 20th, 2009[...] und lässt sich sowohl dynamisch als auch von Hand erstellen. Richtig gute Anleitungen zum Thema gibt es bei thecssninja und auf [...]
iFUN.de/iPhone :: Alles zum iPhone − Offline, mit Icon und im Vollbild: Tipps für den Entwurf eigener Web-Applikationen, December 30th, 2009can you please help me … am new to web apps but produced one using Dashcode 2.04 as only have leopard not snow leopard and need to now make the app available for offline use. Can someone tell me how to do this ? I can see from another blogg that Dashcode 3 does this for you . But i do not want to do the whole app again . Any offers on this? would be very grateful if anyone can help as there is not a lot of info on dashcode around. I know i need to create manifest but need simple guide after producing the files and deploying. thank you
nerissa, January 2nd, 2010I don’t use dashcode so I can’t help you there. I imagine updating your dashcode version won’t require you to do the web app again.
The Css Ninja, January 2nd, 2010hi there sorry just if you could let me know how to make a manifest from the files I have deployed from Dashcode anyway please. Is it the same process you have above. thanks
nerissa, January 3rd, 2010Thanks, worked flawlessly.
Dae, January 9th, 2010hi all,
just a question:
what’s the easyest way to let the user “switch” from “local” and “not local” (without manifest)?
(allowing to download the app “data” only on request?)
using PHP would be useful to include() or not the .manifest, but i wonder how to “persist” the state because PHP is processed on the server-side before client execution…
thank you in advance for any advice…
Joachim, January 15th, 2010cookies?
Joachim, January 15th, 2010@Joachim – cookies could be a good option you can then check with PHP if it’s local or not.
The Css Ninja, January 15th, 2010thanks! this was my initial idea… I was wondering if there are other (better?) options…
I’ll try it this way
have a nice day
Joachim, January 15th, 2010Joachim
Cookies and a php controlled manifest works well.
It is possible to implement a user button in the app to clear the cache which sets a cookie which causes php to return an empty manifest. Javascript can be used to force immediate reloads to complete the implementation.
It can get hairy debugging the sequence but once you have it working it seems to be reliable.
GeoNomad, January 16th, 2010I’ve got a question for Mike D.
I’ve been busy creating a very cool webapp and now I want to get it in the apple store.
Can you explain what you mean with: “build our own caching that reads the manifest”.
Thanks
Max
maxmakes, January 17th, 2010Hi Ninja and GeoNomad,
I’m developing an iPhone web app that utilizes cached data. The dialog here has been invaluable to debug various problems I’ve encountered.
I, too, have used a dynamically generated manifest file, but even though the content type is clearly “test/cache-manifest” (thanks web-sniffer.net), the status of the applicationCache is Uncached. Static manifest files work just fine.
Geonomad, did you set any other headers other than the Content-Type?
Thanks
CrazyIvan
CrazyIvan, January 19th, 2010Hi CrazyIvan, if you’re are still getting uncached status even though the mime type is correct. This usually means your are referencing an asset that doesn’t exist or you have the wrong path to one or more of your assets.
The Css Ninja, January 19th, 2010No other headers were needed.
As Css Ninja says… look for non-existent items.
When debugging, if something had gone wrong earlier, sometimes a respring of the iPhone was necessary to get cacheing to work again.
GeoNomad, January 19th, 2010No problems with the files listed in the manifest.
There was a newline before the CACHE-MANIFEST header. I was using Web-sniffer.net, but I didn’t have “Raw HTML View” selected. Without that option checked, the newline is not displayed.
I knew that CACHE-MANIFEST had to be the first line, but the way I had written the ASP created a “hidden” newline. See below:
The altered layout below corrected the issue:
Thanks,
CrazyIvan
CrazyIvan, January 20th, 2010Hi Ninja,
Your demos and this discussion have been invaluable.
I am using an iTouch 3.1. In my tests I can open both a .pdf and a MS Word .doc file in mobile Safari while on line. If I list only the .pdf in the cache manifest file, it gets cached with no errors. This is good.
If I list the .doc file in the manifest, I get an error event when loading the cache and the .doc file is not cached, even though it views OK when on-line. The manifest file is super simple and there are no typos. Here is the file:
CACHE MANIFEST
index.html
cache_debug.js
test.html
test.pdf
test.doc
Leave out ‘test.doc’ from the manifest and everything is cached without errors. Put it in and we get a cache error even though the server downloaded with 200 OK.
Here is the test with the .doc in place. Open the .doc while on line, it works, but it is not cached.
http://sky-report.com/test/cache-test/index.html
Have you heard any more on this? Does safari only cache a limited set of file types? It is strange that it fails to load the .doc into the cache.
Also, do you know how to see the specifics of the error event? I am trying to see why safari is throwing an error on the .doc.
THANKS!
Pb, January 29th, 2010[...] This article has gotten me started. [...]
Caching content « fredsherbet.com, January 29th, 2010That’s an interesting find, there could be an undocumented list of files that will not be cached. So far we know audio, video and now doc files don’t cache. The audio and video is due to them opening in an external player but doc I’m not sure why it wouldn’t cache. I tested the page in firefox and everything caches fine including the .doc file, this leads me to believe mobile safari may have a balcklist of files it won’t cache?
One theory could be that it won’t cache propriety formats, which would make all office documents fail when trying to cache. You could try saving the .doc as .rtf instead and see if that works?
The Css Ninja, January 30th, 2010Hi Ninja,
I have updated my test at
http://sky-report.com/test/cache-test/index.html
with an .rtf file instead of the doc. It behaves the same. I have some cache event logging so you can watch. It gets the file with 200 OK, but the DOMApplicationCache throws an error as soon as it hits a .doc, .rtf, .xls, and .ppt. Which are all files that can be opened by safari while on-line.
So here is another theory. Mobile Safari may have a plug-in structure similar to other browsers, so it will render files of different types using its plug-in. We see that with PDF, audio and video. I believe in iPhone 2.x, the PDF would not cache for offline viewing.
So this problem may not be a Safari problem in-as-much as a plug-in not being cache-aware.
I think safari can also open some apple formats, I will try those also. More theories, testing and comments are welcome.
BTW – how do I submit these questions to Apple? I have the free Dev registration but not the $99 yet. THANKS NINJA – YOU ROCK!
Pb, January 30th, 2010That sounds quite plausible that the plugins may not be cache aware for certain file types.
You can try the devforums, not sure if you need a paid account to get access. You could also file a bug.
The Css Ninja, January 30th, 2010Hey Ninja,
Since I couldn’t get this to work, I downloaded the source and uploaded it up another server. When o Reyes to so this again, it didn’t work like on your site.here is my testing link:
manifesttest.atspace.com
If you can tell me why this is so.
Thanks,
Gerome, February 3rd, 2010Gerome
@Gerome – See GeoNomads comment for a useful tool to let you know if you are sending the manfiest through as the right mime type. Running your one returns text/plain you need to setup on your server to feed all .manifest files as text/cache-manifest.
The Css Ninja, February 3rd, 2010