Clearing a UIWebView’s Browser Cache

While writing a hybrid native/web application for iOS, I encountered a problem I never even bothered to consider before starting:

How do I clear the browser cache for the application?

Clearing cached HTML resources, scripts, and stylesheets is the type of browser-provided functionality that is easy to take for granted. However, when writing an application with a hosted UIWebView, you’re suddenly solely responsible for handling little issues like this.

Thankfully, programmatically clearing the browser cache for an iOS application is simple:

[[NSURLCache sharedURLCache] removeAllCachedResponses];

If your also interested in clearing out cookies, then also include this:

NSHTTPCookie *cookie;
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [storage cookies])
[storage deleteCookie:cookie];

When and where to invoke this functionality is really up to the particular circumstances of your application.

While clearing the browser cache is the right approach for certain problems, it’s not the answer to every cache-related problem.  If you’re interested in bypassing the caching of web resources all together, be sure to look into NSURLRequest‘s NSURLRequestCachePolicy rather than aggressively clearing the application’s cache.

Why Won’t Internet Explorer Change the Appearance of an HTML Element I Changed via JavaScript

A very common technique in modern web applications is to dynamically change the appearance and/or behavior of an HTML page element via JavaScript. Often, this is done by modifying the style property of the object to apply different CSS rules to the element or by changing the layout and dimension properties inline.

The Problem

While building an application like this, you’ll likely quickly discover that Internet Explorer (at least the ~version 8 variety) doesn’t apply some of these changes when you expect, and often need, it to. The change will either appear to be applied at some random point significantly after the change to the style is made or appear to never be applied at all.

The Apparent Cause

What’s actually happening appears to be a performance optimization in these older versions of IE. It appears that the browser makes the explicit choice to defer some style changes for as long as possible. From what I can tell, the browser assumes that the layout of the page should stay largely static until something that would significantly impact the layout happens such as resizing the window.

At least that’s what appears to be happening. I don’t know specifically what decisions were or weren’t made by the development team. But I find that viewing the problem in the way I describe above helpful in understanding what is happening and how to work around the behavior.

How to Cope with the Issue

A solution to this issue is to “nudge” IE into applying the styling changes when you want. The way to do this is to reference a property in the element’s style property that IE believes it requires styling changes be applied to properly calculate. Referencing the offsetHeight property seems to work rather well in most cases.

var nudgeByReading = elem.offsetHeight;

Simply reading the property may be enough to trigger a re-layout.  However, simply reading the property often isn’t enough.  Frequently, you’ll first have to change the property and then reference it to force the re-layout.

To force a redraw regardless of style changes, you can write a method that makes an innocuous change to the style, read the property, and then reverse the “fake” style change, like so:

var savedDisplayStyle = || ”; = ‘none’;
var nudgeByReading = elem.offsetHeight; = savedDisplayStyle;
nudgeByReading = elem.offsetHeight;

To be safe, you may want to consider universally reading and writing to the property to force the recalculation just in case simply reading from the property doesn’t force the redraw.

Some Notes on Applying the Technique

One thing to remember when using this technique is that changing the layout of a parent element will force a layout calculation of each of the parent’s child elements. So, if changes are made to multiple elements that have a common parent, forcing a redraw of the parent will cause a redraw of each child.

Doing this may result in cleaner, more resilient code. But do keep in mind that forcing a redraw at a point too high in the DOM hierarchy (such as the “body” tag for example), will cause most or all of the page to redraw which may cause performance problems. As a rule, it’s a good idea to redraw as few elements on the page as possible.