Category Archives: Development


Introducing SpiralKit

A little more than a year ago, I released my first iPhone application, Spiral by Digital Generalists.  After several updates and many happy customers, I’ve decided to release the drawing engine for Spiral as an open source framework through my company, Digital Generalists, LLC..

What Is SpiralKit

SpiralKit is a Quartz 2D-based drawing framework for iOS written in Objective-C. The framework enables ‘drawing’ on a UIView in an iOS application and ships with pen, highlighter, and eraser drawing effects.

The framework is built specifically to enable easily adding new effects, color spaces, and drawing algorithms in a modular fashion. If you want to provide a unique drawing effect, support of the CMYK color space, or a custom drawing algorithm, you can add such features to SpiralKit without having to modify the fundamental components of the framework.

Where to Find It

The project is hosted on GitHub at

More Information

See the release post on the Digital Generalists site and the framework documentation for all information about using SpiralKit in your application.


Introducing Assurance

Over the last few months, I’ve been working on a project and, today, I’m releasing the result of that project as Open Source Software. Assurance by Digital Generalists is an application that enables comprehensive file and folder comparison with tools to merge data on multiple operating systems.

Where to Find It

The project is hosted on GitHub at

Inspiration for the Application

Over many years, I’ve collected a substantial library of electronic files ranging from simple text documents, spreadsheets from the very early ’90s, games, MP3s, videos, email archives, source code, etc… Because I had so much stuff, I had backups…plural. And backups of backups. And some stuff was on thumb drives because I needed it to be portable at some point. And some stuff eventually moved to newer machines, but I never deleted the copy on the older machine.


In short, I came to a point where I wanted to be able to compare the many copies of my digital archive, eliminate the redundant stuff, know where the latest version of everything was, and move things into a ‘repository-of-record’.

I easily could have purchased a tool to accomplish that task. There are highly-rated options available. Or I probably could have written a shell script that would have done the job from the command line.

However, I felt the problem presented a good opportunity to try out several software development frameworks and techniques I’ve been interested in learning more about. So I wrote Assurance instead.

What Is Assurance

Assurance is a cross-platform, client-only application written in Java that leverages both Spring and Hibernate with a Swing-based UI.

At it’s core, it is a tool to comprehensively compare and optionally synchronize the contents of files and directories.

While on first glance, Assurance may appear to be a good fit as a backup tool, it wasn’t really designed for those needs.  A backup tool should provide features like scheduling of jobs, conflict resolution, automated monitoring of the file system, one-click system restore, etc…  Assurance wasn’t built to solve those problems.  Assurance is very good at comparing files and directories and provides tools to manage differences.  It does those jobs well, but doesn’t claim to do more than that.


Assurance is released under the Apache License 2.0.


The following tools need to be installed to build Assurance:

The Maven configuration will download and install the appropriate versions of the following tools:

  • Spring Framework
  • Hibernate
  • JUnit
  • H2
  • Apache Commons
  • Apple Java Extensions
  • SLF4J
  • Log4J

The following dependencies are required to run binary distributions of Assurance on Windows machines:

Mac distributions of Assurance package the appropriate JRE with the application bundle, eliminating the need to separately install Java on a Mac to run the application.  Windows distributions require that the JRE be installed prior to starting the application.

Building and Packaging

Assurance uses Maven as its primary build and dependency management system.

To build the application:


cd project_root/assurance
mvn clean package -Pdevelopment


cd project_root\assurance
mvn clean package -Pdevelopment-windows

To run the unit tests:


cd project_root/assurance
mvn clean test -Pdevelopment


cd project_root\assurance
mvn clean test -Pdevelopment-windows

To package the application for internal release:


cd project_root/assurance
mvn clean package -Pintrelease


cd project_root\assurance
mvn clean package -Pintrelease-windows

To package the application for release:


cd project_root/assurance
mvn clean package -Prelease


cd project_root\assurance
mvn clean package -Prelease-windows


Assurance was developed using Spring Tool Suite 3.6.1. Project files for the IDE are included with the distribution.


Assurance includes a modified version of the


class from the iBATIS Apache project.

Why a Digital Generalists Product?

Digital Generalists serves as the primary way I deliver products to the world. For full products, I want Digital Generalists to hold the copyright and serve as the primary entity releasing the software to the world.

The fact that Digital Generalists, rather than me personally, is the entity releasing the product, doesn’t affect or impact how you can use the software.  As long as you abide the attached software license, you can use the product and source as you wish.


Evaluating a Proposed Application Architecture

At work, I’ve recently had a few conversations about the best way to evaluate candidate architectures for a software project, so I decided to put down a few ideas I have on the topic.

Project Intake

Firstly, there are several questions that need to be answered and understood by all stakeholders of a project before you can properly evaluate an architecture:

  • What are you planning to build?
  • Why are you building it?
  • Who are you building it for (i.e. who is your audience)?
  • How will success be measured?

At a technical level, most projects start with an answer to the first question and have a weak or vague understanding of the other three. However, if you can’t answer those three questions, you don’t have a good justification for the answer to the first one.

The first task is to get agreement on the answers to Questions 2 through 4 and verify the answer to Question 1 still fits. If it doesn’t, use the opportunity to identify what can be built that fits the needs of the answers to Questions 2, 3, and 4.

Business Environment Analysis

Most technical ecosystems have processes and expected technical standards that apply to all applications within the ecosystem. Your organization does things a certain way.  Your team likely has expertise in a specific technology.  Your business also likely has requirements around protecting the environment and facilitating support of the application.  These factors should be identified:

  • How are applications expected to authenticate and authorize users?
  • Are there standards around data security?
  • Are there standards around data retention?
  • Are there standards around transport protocols?
  • Are there expectations around supported platforms?
  • Are there standards around accessibility?
  • Are there standards around logging?
  • Are there standards around analytics?
  • Are there expectations or standards around interoperability across applications?
  • Are there standards regarding UI conventions?
  • Will the new product provide technical challenges to existing distribution and delivery models?
  • Will the new product provide technical challenges to existing support mechanisms?
  • Are there standards around code documentation?
  • Will the new product provide technical challenges to existing documentation procedures?

The answers to these questions will identify many of the inherent technical requirements of the system. These aspects are related to the notion of certifying the application as “good and complete” as your organization defines that term, even if informally.  If there is no formal certification process, either within your company or externally, for the application, answering these questions will help define what “good and complete” means to your product.

Technical Environment Analysis

The next step is to identify what you already have in place and how the new product will fit into the overall ecosystem.  Few applications are 100% greenfield with zero dependency on existing systems, so it is paramount to understand what environment you will be working with.

  • What systems are already in place?
  • What role will those existing systems play in the new product?
  • How will the new system affect seemingly unrelated products?
  • What types of access privileges are required to interact with these systems?
  • What integration facilities already exist in the identified systems?
  • What data does the new application need and where can it pull that data from?
  • In what formats are the data accessible?
  • What second-level dependencies exist?

Technical Architecture Review

At this point, we should have enough information to apply a proper architecture review. Firstly, you verify the proposed architecture addresses all of the concerns identified in the Business and Technical Environment analyses.

After those business-related concerns are addressed, most of the remaining aspects of the architecture will be technically focused.  However, technical concerns tend to be highly domain and context specific.  The meaning of “good and complete” when it comes to these technical concerns will be influenced by the programming language, platform, organization, and product. In general though, the following concerns tend to apply regardless of context and can be used as a base set of technical concerns to review regardless of project:

  • Separation of Concerns: Each component of the system should only do one thing and do it well. In practice, this minimally means ensuring a strong separation between the business logic implementation and the UI.
  • Abstract Interfaces: Are the touch points between the system integration points and product components done in a way that effectively hides implementation details of both sides of the integration?
  • Scalability: Can the proposed implementation easily scale to accommodate concurrent execution of the same logic processes across different data sets?
  • Maintainability: Is the architecture well reasoned, consistent, and easily modified?

When Should Architecture Reviews Occur?

You do not want an architectural review to impede the development process. Your goal is not to create the “perfect” architecture.  Your goal is to build a solid product.  However, you want to identify issues with a proposed architecture early enough to do something about any problems an architecture may have.

  • Ideally, a review of a proposed product architecture should occur before any coding has begun. (This is nearly impossible to achieve in my experience.)
  • A more realistic ideal is that a full architecture review should be conducted as soon as a potential product’s prototype or alpha implementation is minimally functional.
  • At a minimum, a full architecture review must be conducted as soon as a proposed product reaches the release candidate stage if one has not been completed earlier.
  • A full review should be conducted once prior to the product’s initial release. As soon as this occurs, summary reviews of the architecture will likely be sufficient at subsequent steps of development and maintenance.
  • For ongoing development, a summary architecture review should occur at the start of each new release and again as part of the project’s release criteria (ideally at the end of the last development sprint) or as soon as the first release candidate is identified.

A Reality of New Product Development

Most new products/applications start out as skunkworks projects. Typically an individual or a small group builds a product prototype and uses that prototype to gain approval/funding for the project.  As a consequence,  a new product often starts life with a sizable, un-vetted code base and significant technical debt. The process for bringing these products to production involves:

  • Conducting a full architecture review.
  • Documenting gaps in all of the aspects identified above.
  • Conducting a full code review.
  • Identifying all technical debt as issues/defects in your project tracking system.
  • Prioritizing architectural gaps and identifying gating issues.
  • Creating a plan to address all non-gating issues in a timely manner.
  • Verifying that all gating issues are addressed before the product is released to production.

The process I’ve laid out is intentionally light on specific procedural details because each organization is different and each technology stack and platform carry specific technical concerns.  The mechanics of a formal architecture review process need to be crafted based on the specific needs of your organization and the technology you are using.

However, this outline should provide a good abstract notion of what goes into an architecture review.  The items and concerns I’ve outlined probably aren’t comprehensive.  If you feel I’ve overlooked something important, please mention it in the comments.


Marker Interfaces

Marker interfaces tend to be one of those things that your don’t think about often.  But when you have a problem they can help you solve, you think they are awesome.  The trick is knowing when they should and should not be used.

What is a Marker Interface?

Marker interfaces are basically an interface contract with no methods or properties specified.  The notion of interface contracts are common in many languages but take on many different names.  If you’re familiar with Java interfaces, Objective-C protocols, C++ pure abstract classes, or any similar technique in your language of choice, you know what I’m referring to.

Typically, an interface contract specifies a set of methods that must be implemented by any object that intends to support the contract.  This enables you to refer to an object by the contract (which typically corresponds to a functional role or feature role in the program) rather than the concrete type of the object itself.  This both clarifies how code consuming an object intends to use the object and makes it possible to easily use different concrete classes that also implement the contract without needing to change the consuming code.  The consumer doesn’t care about the concrete object type as long as it satisfies the contract.

So why on Earth would you ever want to create a contract that doesn’t specify any methods?  Most of the time, you don’t. But if you need a way to abstractly specify an object type, especially when the abstract type may have concrete instances that don’t share a meaningful inheritance chain, then marker interfaces are likely a perfect solution.  You most often have a need to specify an abstract object type like this when you have orchestration or coordination code that is transferring objects from one part of a program to another.  The orchestration code doesn’t need to use or modify the object, it just needs to move it from one place to another.

Such orchestration code tends to be both fairly abstract and highly leveraged within an application’s architecture, so you often don’t want to specify concrete types for the objects being sent back and forth.  A simple way of generically passing objects is to specify the parameters of methods in the orchestration code as generic objects.  But specifying transfer method parameters as a generic object has a few downsides.  Firstly, it doesn’t provide any guidance to the caller about what should be passed.  Secondly, literally anything can be passed.  If you accidentally pass an object you didn’t intend to, the compiler/parser won’t catch the error.

void transfer(Object data)

Marker interfaces help avoid these problems.

By using a marker interface, you can specify the intent of what should be provided to the method without restricting you to a specific type or inheritance chain.

void transfer(IFooDataObject data)

This method signature is much clearer to the person using the method what type (in the functional intent sense of the word) of object should be passed to the method.  Any concrete type can still be passed, but you have to make a conscious choice about which objects should be allowed to be passed by adding the marker interface to the type definition of the object before you can pass an object of that type. In a mature architecture, prior decisions about which objects carry this declaration can greatly minimize confusion about what to send where.

You also get a level of type checking via the compiler, so if you accidentally pass a reference to a UI control object instead of the data property on the control you intended to pass, the compiler can let you know.  Without the marker, it wouldn’t.

This technique of using marker interfaces for high-level type specification is really the one application of marker interfaces I use frequently.  I tend to not like using marker interfaces to direct flow of control within an application (i.e. “if foo implements bar then do x”) because I think such control flow is typically better governed by object state than by type. But that thought is probably worth a post of it’s own.

Four Star App Review

To Aspire to 4 Stars Rather than 5

A happy side effect of app stores and the web in general is that feedback ratings on a product are no longer difficult to find. There was a time not long ago when a consumer would need to turn to a respected source, such as Consumer Reports, to get a general consensus of quality for all but the most ubiquitous and popular products. Such a world, where information is funneled through a few curators, is one ripe for “reputation management.”

In theory, to optimize the perceived quality of your brand, all you would need to do as a company providing a product or service was:

  • build to the desires of the known entities who will be doing the evaluating
  • or figure out how to skirt the evaluation process while still presenting an air of broad market approval
  • or establish a relationship with the people doing the evaluating to ensure friendly terms
  • or even more unsavory behavior

But in a world where every potential customer is also a potential reviewer of your product/service, such brand management tactics lose some of their efficacy. To be sure, a fair amount of the behaviors mentioned above still happen, but they are not as universally effective as in days past.

One of the new realities we as product creators are faced with is that universal cultural approval, at least as we came to understand it over the last 50-odd years, is something largely unattainable. Nothing ever truly had this type of universal appeal, but the difference is that now every critic has, at least potentially, as loud of a voice in the conversation as the traditional curators do.

This is a good thing. Focus-grouped products engineered for mass appeal, be they music, literature, software, movies, or television, are, generally speaking, lowest-common-denominator creations…things without soul, passion, or inspiration because they are so deliberately engineered to speak to so many people. They are built to appeal to everyone in a shallow way and are done so to such a degree that they ultimately speak to no individual in a meaningful way at all. That intimacy has literally been factored out of their very being.

But one odd effect of this mass availability of opinion is that such a world can be crippling for those product creators starting out and looking to become established. “What if we get a bad review early? What if someone hates it?” The old answer was to quietly address the complaints of the people who hate it through largely private communication. The new answer is a little more nuanced.

You still have to address the complaints, but now we do so much more publicly.  This requires a thicker skin than in years past. Part of serving our customers now involves owning up to our mistakes or misjudgments in the open.  The process of managing the perceived quality of your brand has shifted from crafting a potentially artificial image of “everything is great all of the time” to one of concentrating on the good while acknowledging the slip ups and working diligently to ensure the good far outweighs the missteps.  “Yes, a few people hate it. Let’s concentrate on keeping it just a few people.”

Acknowledging missteps can be a very stressful thing, especially for those striving to establish themselves.  A single negative opinion can feel like the end of the world when you’re fighting so hard just to get attention.  It’s hard not imagine all of the potentially negative things that could result from a bad review.  But you can’t let yourself get trapped focusing on the “what-if”s that may or may not come about because of something you truly cannot prevent.

If you receive a bad review, you got a bad review, and you have to deal with it. Pay attention to it. Listen to what the customer is saying. If they are asking for something reasonable, something completely within your vision for the product, then there is no reason not to give them what they want, especially if it’s easy to do.  Start a conversation with the customer and come up with a plan for addressing the things they don’t like.  Attentively responding to customer feedback is surprisingly effective at fending off the scary consequences of a poor review.

But this doesn’t mean that you should blindly defer to the opinions and desires of every person who comments on what you are doing.  If you built a Volkswagen and a customer is complaining that it’s not a Cadillac, that’s not necessarily an indicator that there is something wrong with your product. They may just be trying to get a Cadillac below cost. The same rule applies doubly if you built a boat and someone complains that it’s not an airplane.  In these cases, the problem you should address is likely not your product itself but how you are positioning it within the market.

You cannot please everyone. You just can’t. If you came of age in the time when all opinions you heard in media mattered, then this feels very wrong. And you’ll want to fix every complaint from people you don’t know right away and completely. But you’ll also be lapped productivity-wise by those who’s attitude largely boils down to: “Yeah, there’s one guy in Idaho who hates what we’re doing. Thank goodness that almost all of our other customers love what we’re doing.”

In today’s world, a perfect 5 star rating is nearly impossible at any scale that would represent success. You have to be okay with a few people who don’t like how you built your product. Know in advance someone will be a real jerk about your creation. Concentrate on building something that will average a better than four-star rating, factoring in the cranks who will positively hate how you designed your product no matter what you create, especially those who don’t understand what you built.

If you do an exceptional job, you may even average 4.9 stars and become a legitimate hit. Even if you don’t, you’ll likely build something you, as the creator, have greater faith in. And that matters much more than the opinion of that one guy in Idaho.

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.

How to Convert a String Representing a Unicode Character Sequence to the Unicode Character

I recently received some translated resource files from the Translations team at work.  To my surprise, all of the files, even those for double-byte languages, were returned in ASCII encoded files.  After some inquiry, I found out that because of the technical limitations of a proven legacy system, all translation files were encoded as ASCII.  What this meant is that I was confronted with a set of ASCII text files containing Unicode escape sequences (\uxxxx) that I was responsible for converting to a proper Unicode encoding.

While solving the problem, I came across a couple solutions for converting Unicode escape sequences to a different encoding.  The first was to use the StringEscapeUtils class in Apache Commons Lang.

String lineOfUnicodeText = StringEscapeUtils.unescapeJava(lineOfASCIIText);

Using the StringEscapeUtils class is very straightforward; simply read the contents of the the ASCII file line-by-line, feed the line of data in to the unescapeJava method, and write the unescaped text to a properly-encoded new file.  But this technique requires writing a utility program to feed the contents of the ASCII files into the StringEscapeUtils methods and then write the transformed string to a new file.  Not hard to do, but much more work than ideal.

The second solution is to use the native2ascii utility included with the Java JDK.  The utility can take the input file and perform effectively the same unescape transformation that Apache Commons does.

native2ascii -encoding utf8 c:\source.txt c:\output.txt

A very simple solution that works as advertised.  No quirks or caveats that I’ve noticed.  There’s even an ANT task for incorporating native2ascii into build scripts.

Setting a Custom User Agent in Objective-C

Sadly, it is a common scenario in web development to have code that handles specific browsers, or classes of browsers, differently.  The practice largely has it’s roots in the “bad-old-days” of having to handle the many various quirks and idiosyncrasies in the different CSS and layout engines of the major browser vendors.  Thankfully, this problem is getting, largely, better (at least in my experience), and the need to write browser-specific code of this type is becoming less of an issue.

But handling layout differences across browsers isn’t the only reason to treat different clients uniquely.  Dropbox’s matching of the sort order paradigms of either Windows or Mac depending on which OS the site is being viewed on is a practical example of when functional differentiation is desired for different clients.

Dropbox on Mac

Dropbox on Mac

Dropbox on Windows

Dropbox on Windows

These techniques are nearly always implemented by inspecting the user agent string provided in the headers of each request the server receives.  Each browser provides a user agent header that describes the type, version, OS, and other relevant details about the client sending the request.  For a web application, the client application is the web browser, so you don’t need to worry about specifying one, the browser provides it. You only need to worry about consuming it if necessary.

But what about hybrid native applications where mobile content is running within a web browser control (such as UIWebView in iOS) within a native application.  By default, the web browser control typically sends a subset of the user agent string the full-browser version would send.  But what if you want your server code to recognize when your native application is submitting requests?  How can you specify details about the native application in the user agent string if you need the backend application to behave differently for these hybrid clients?

In the iOS SDK, the answer is to modify the UIWebView’s user agent string for your application.  This is easily done by:

– (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
NSString *existingUserAgent = [[[UIWebView alloc] init] stringByEvaluatingJavaScriptFromString:@”navigator.userAgent”];

NSString *newUserAgent = [NSString stringWithFormat:@”%@ custom-information-about-my-application”, existingUserAgent];
NSDictionary *userDefaults = [[NSDictionary alloc] initWithObjectsAndKeys:newUserAgent, @”UserAgent”, nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:userDefaults];

/* … your application code … */


The essence of the above code is that the existing UIWebView user agent is retrieved from a UIWebView instance (it doesn’t need to be the instance that will actually display the content), the custom user agent information is appended to the original user agent, and then the new user agent is registered to the user defaults of the application under the key UserAgent.  This will set the user agent sent for all network requests sent from your application’s code, including raw NSConnection requests.*

In my experience, you should always augment the existing user agent rather than completely replace it as the server will likely make some assumptions about whether you are a supported client and what flavor of display code to deliver based on the web view control’s existing agent string.  This is especially true in large applications where you don’t own every aspect of the server code.

* NOTE:  Things can get a little weird for requests issued from a linked library (like making an API call such as stringWithContentsOfFile).  Therefore, it is dangerous to assume that EVERY server connection issued by your application will carry the custom user agent. Your milage may vary, so verify that the custom agent is being applied uniformly for all calls and adjust how the agent is registered if needed.

Fun with Simulators and VMs – Can’t Delete an Application from the iOS Simulator

For the most part, Apple’s simulator environment for iOS (both the iPad and iPhone), does a pretty good job.  There are mountains of odd “simulator-only” bugs and some obvious features are simply not implemented (three-finger+ gesture emulation anyone?).  However, as anyone who has worked with device emulators other than iOS’s can likely attest, Apple’s offering more than holds its own in terms of features and usability.

That said, the quirks and bugs can drive you mad.  The latest one I’ve noticed is that I am no longer able to uninstall an application from the simulator using the iOS “uninstall” feature (i.e. tap and hold the application’s icon until it starts to shake, then press the ‘X’ in the corner to remove the application).

This isn’t a big thing as re-running from the simulator will reliably (in my experience) replace the existing binary on the simulator.  However, there are times when I want to completely remove the application to remove things like the Settings bundle or resource and data files stored in the bundle directory of the application on the simulator.  The easiest way to do this had been to uninstall the application via iOS itself.

However, in the 6.0 or 6.1 SDK (I’m not sure when I first noticed, and I’m not motivated enough to track down the specific release the bug was introduced), the “uninstall” feature stopped working.  Tap and hold will still cause the icons to shake and the ‘X’ to appear, but pressing the ‘X’ causes the simulator to lock up.

The work around to this is simple.  You can just delete the application bundle directory from the simulator’s install directory on your hard drive.

Open the terminal and cd to:

cd “~/Library/Application Support/iPhone Simulator/6.1/Applications/”

Change the “6.1” in the above path to the version number of the simulator where the application you want to remove is installed.  If you issue an ls command in this directory, you’ll see a list of directories with GUIDs for names.  Each directory represents an application deployed to the simulator.  Find the directory for the application you want to remove and delete the directory

rm -r <GUID>

Nothing complicated, and for people comfortable with the terminal at least, an easy method for clearing a deployed application from the simulator.