Search
Goodies

Social Networks
Designs I Like

Entries in programming (22)

Sunday
Jun052011

Poll: When using external library, do you study how it works?

Tuesday
Apr262011

How an application handles version upgrade

With each release of a software, comes the burden of handling version upgrade: the process of modifying, updating, adding or cleaning stuff in the software internal data structures in order to use the new features that comes with each version of the software. The upgrade process usually happens at application launch time and should be fast enough so the user doesn't notice what is happening. This is certainly the case of all iPhone applications.

With every version of Ultimate Password Manager, the following is done at application launch time:

  • Check what version of the application we are running, if older, we need to start the upgrade process. 
  • Make updates to the application internal data structures to support the new features. 
  • Show a UIAlertView to inform the user that the upgrade took place; 
  • Set a variable in order to eventually ask the user (3 days after the upgrade) to write a review in the App Store about the new version features. 
  • Update the version number variable to the current version number of the application so that we know when this version will be updated in the future. 
The following diagram shows the application logic flow in order to handle version upgrades.
Creating data structures the first time

When the application was first released, a specific amount of setup was done to create the internal data structures for application runtime. NSUserDefault is used as data persistence storage. This is the baseline for the future upgrade process for users upgrading to a newer version. Modifications required to this baseline should be considered a delta. Here is a excerpt.

// initialize default application settings
// Initialize the NSUserDefaults values and write them to disk if this is first time launch!
[defaults setInteger:1 forKey:kFirstUseKey];
[defaults setInteger:0 forKey:kpasswordTypeKey];
[defaults setInteger:0 forKey:kshowTipsKey];
[defaults setInteger:0 forKey:kKeepPasswordHistoryKey];
[defaults setInteger:0 forKey:kShakeForNewPasswordsKey];
...

At the end of the block, with each release of the application, modifications made to the base data structures is done with successive calls to a method called ImplementVersionXXX. With each release of the application, a new call is added in the serie and in each of these method, modifications to the baseline data structures are done there.

[self ImplementVersion101];
[self ImplementVersion110];
[self ImplementVersion111];
...
[self ImplementVersion202];
[self ImplementVersion210];

The content of any ImplementVersionXXX is very simple:

-(void)ImplementVersion101;
{
     [self UpgradeFrom100to101];
}

So in fact, implementing a version is a set of calls to upgrade the baseline data structures from version X to Y to Z.

Upgrading from version X to version Y to version Z

The upgrade process needs to take into account a very important fact: not all users upgrade their application at the same time. Some users may even skip many releases. For user A, the application may be upgraded from: version X then to Y then to Z but for user B, the upgrade could be from version Y to Z if the user bought the version at release Y time frame ! Here is a graphic illustrating this.

Upgrading to current version

If the user download an update from the App Store, we need to know from, when the application is next launch by the user, from which version we need to upgrade. Here is how the check is done:

if (currentVersion == kRelease100) {
    // We upgrade: 1.0.0 to 2.1.0
    [self UpgradeFrom100toCurrentVersion];
    [defaults setInteger:kRelease202 forKey:kschemaVersion];
    [defaults synchronize];
}
...
if (currentVersion == kRelease202) {
    // We upgrade: 2.0.2 to 2.1.0
    [self UpgradeFrom202toCurrentVersion]; 
    [defaults setInteger:kRelease210 forKey:kschemaVersion];
    [defaults synchronize];
}


if (currentVersion == kRelease210) {
    // This is the current release, we cannot upgrade from the current release !
}

Then, the content of a UpgradeFromXXXToCurrentVersion is very simple:

-(void)UpgradeFrom100toCurrentVersion;
{
    [self UpgradeFrom100to101];
    [self UpgradeFrom101to110];
    [self UpgradeFrom110to111];
    [self UpgradeFrom111to120];
    [self UpgradeFrom120to200];
    [self UpgradeFrom200to201];
    [self UpgradeFrom201to202];
}

The content of any UpgradeFromXXXtoYYY is very simple:

-(void)UpgradeFrom111to120;
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setInteger:1 forKey:kshowLiveFeedback]; // new in 1.2
    [defaults setInteger:5 forKey:kQtyOfPasswordsToGenerateKey]; // new in 1.2
    [defaults setObject:[NSDate date] forKey:kInstallDate]; // new in 1.2
}

Now, a graphic illustrating all the method calls and how they relate to each other.


There you have it, Ultimate Password Manager is build juts like that to process upgrades of itself.

Sunday
Dec192010

MyDevNotes - for beginners

When I first started to learn iOS app development and design, I started a little web site with all my dev notes. You can find it here: http://www.tinysofty.com/MyDevNotes/Start_Here.html. For beginners only. I might redesign this web site sometime in the future.

My Dev Notes - a simple reference web site that I started at the beginning of my iOS journey

Friday
Nov192010

Writing iOS apps with high level frameworks and languages

Recently, a friend of mine asked me to test one of his iOS app he was working on for a while. A very simple app that is used to fill a very specific need. He wanted my feedback on the app (stability, user interface, wording, etc.). So I installed the whole thing on my iPhone 3GS and gave it a serious look.

After a while, I noticed this app was doing weird things visually:

  • animation of complete views that I was not aware we're available in UIKit;
  • text fields that we're a bit strange looking;
  • navigation bar at the top was moving up and down as I was scrolling the whole table view (that one was the most surprising: the navigation bar never scroll with a table's content!);

Once I was done with my tests, I decided to FaceTime this guy and give him my impressions. They we're mostly positive and I think I've helped him get a few things corrected. When I was showing the navigation bar moving with the table's content, he was not surprised at all. He said: "oh yeah, this is expected as the whole view is a UIWebView with complete HTML/CSS implementation of basic iOS interface elements". What?

This developer is actually using a framework called jQTouch. More information is available here: http://jqtouch.com/. Honestly, I felt a bit deceived. I felt that way because I thought this developer was trying to have it easy! Why not develop in full Objective-C? Why not a native application? The debate was open!

This is not the first time these questions are asked. And this won't be the last time too. After my initial reaction, I changed my stance. I tried to understand his motive for using jQTouch. I think they are reasonable. He wanted to write his first iOS app that is easy with tools that gives fast results. On top of that, the developer is already fluent with web programming languages. So, He went with what he was knowing best. How about the application quality then?

On the application quality, I can see there is a bit of a difference because I'm a developer myself. But, what about the normal user? They don't really care as soon as the app is usable and produce the desired result. I think this is fine. But, the same day, I had a chance to try this application: Ars Technica Reader for iPad (link to the article presenting the app and the behind the scene view!).


They developed this application with HTML5, CSS and JavaScript. They wrapped this stuff in an application wrapper called PhoneGap. The result? Great on paper. Very Bad on the iPad actually. Sooooo bad. Other users seems to agree too.
In this case, using non native language to develop an iOS app is a complete failure to seize an big opportunity. The app is so slow on a device that is known to be so fast. I wonder why this app could even be developed until the end without being scraped and rewrote in native language.

What does this story boils down to?

  1. A developer can use high level framework or language to write an application, a very basic one. And this is ok!
  2. A developer with very challenging application should avoid using these high level languages. They produce portable garbage that can easily go from iOS to Android but this only serves the developer, not the user. 
  3. I understand why Apple was so hesitant to relax their approval rules. Now, we see in action what garbage these tools are capable of. 
  4. HTML5/CSS/JavaScript seems to get a lot of press these days. But in fact, are they the path of future app development on mobile device? I don't think so. They don't produce optimized results. They are too slow. Yes they produce outstanding things from a browser perspective but that is it! Mobile platform are much more than only webkit-based browsers. 
  5. The App Store is bloated with natively written applications that are very badly designed too. This is not my point. My point is having too much of an emphasis on the tools used to write the app, we loose focus on the objective: writing app that are useful, easy to use and enjoyable. Just like the iPhone.
My two cents worth opinion. What is your opinion?

Wednesday
Nov032010

RegexKitLite: replacing it with Apple's NSRegularExpression

In Ultimate Password Manager, I'm using the very popular RegexKitLite for a few pattern matching with regular expression. Here is a few line of code using this:

NSString *regExpressionUC = @"[A-Z]"; // RegEx: /[A-Z]/g

/* Find all occurences of uppercase letters ? [A-Z] */
NSArray *occurencesUC = nil;
occurencesUC = [passwordTmp arrayOfCaptureComponentsMatchedByRegex:regExpressionUC];
nAlphaUC = [occurencesUC count];
This code is possible with the use of RegexKitLite.

When iOS 4.0 was presented earlier this year, regular expression support was mentioned (indirectly on a slide) as something new. 
So, I thought that I would replace RegexKitLite with Apple implementation. The previous code will now look like this:

NSError *error = NULL;
NSRegularExpression *regExpressionUC = [NSRegularExpression regularExpressionWithPattern:@"[A-Z]" options:0 error:&error];

nAlphaUC = [regExpressionUC numberOfMatchesInString:passwordTmp options:0 range:NSMakeRange(0, [passwordTmp length])];

Better code if you ask me because I'm not dealing with arrays of occurrences but numerical values that represent the occurrences count. Simpler code, less bugs.

Wednesday
May122010

Speeding up application startup time

One one the thing I want to improve with Ultimate Password Manager is the application launch time, particularly on the first application launch. Currently, on the first generation iPod touch, one of the slowest device, the application launch time are:

Application first startup launch times:

  • Version 2.1.0.175: 12 seconds
  • Version 2.1.1.185: 13 seconds

The time is measured from the touch of the application's icon on the iPhone home screen to the first visual change in the user interface while looking at the default splash screen. This is a good measure because this is the most critical period where the user's perception of the application speed is in full swing. I could extend that measurement to include the time for the application to become fully operational but since my application animate its splashscreen, this is less required as the user watch the small animation occurring.

After optimizing the application delegate method applicationDidFinishLaunching, the new launch time are:

2.2.0: 5 seconds

For all versions of my application, the application launch times are 2.5 seconds which is not bad.

How I did the optimization? By splitting the code in applicationDidFinishLaunching as chunk. Before, this method was a long series of steps and tasks that was using to perform application runtime data structures and loading. By splitting these tasks in smaller methods, I can then schedule those in NSOperation queue operations.

NSOperationQueue *queue = [NSOperationQueue new];
// Execute this on a seperate thread
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(formatDictionaries) object:nil];
NSInvocationOperation *operation2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(formatHistory) object:nil];
NSInvocationOperation *operation3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(formatSubstitutions) object:nil];
/* Add the operation to the queue */
[queue addOperation:operation1];
[queue addOperation:operation2];
[queue addOperation:operation3];
[operation1 release];
[operation2 release];
[operation3 release];
[queue release];

Monday
Feb222010

Using HTML files inside your app

Can we include HTML files inside an iPhone application ? Yes! For what purposes ? Reasons to include HTML files could be:

  1. Provide integrated online help into the application;
  2. Provide an easy way to present bunch of text readable offline for static content;
  3. Provide some kind of functionality easier to implement with HTML that pure Objective-C + Cocoa Touch programming;
The way I've integrated HTML files in uP@ssw0rdz! is as follow. First, an HTML file:


This files refers to a styles.css CSS file. Here is the beginning of it:


Now, in Xcode, those files are included this way:


Now, the code. How to read HTML files stored in the application bundle ? Very simple:

-(void)viewWillAppear:(BOOL)animated
{
    NSString *pathToBundle = [[NSBundle mainBundle] bundlePath];
    NSURL *baseURL = [NSURL fileURLWithPath:pathToBundle];

    NSString *pathToFile = [[NSBundle mainBundle] pathForResource:@"Version" ofType:@"html"];
NSString *htmlFileToDisplay = [[[NSString alloc] initWithContentsOfFile:pathToFile] autorelease];
   [self.webView loadHTMLString:htmlFileToDisplay baseURL:baseURL];
   [super viewWillAppear:animated];
}

The key here is to get the path to the application bundle first, then set it as the base URL so that the UIWebView will be able to access the styles.css file that is at the root of the bundle. Se we make the application bundle path the base URL where the style.css file will be stored. 

The result in the application:





Sunday
Feb142010

Improving the SplashScreen: final solution

A few days ago, I've exposed a problem with the startup sequence of my application: uP@ssw0rdz!. See: Improving the SplashScreen on an iPhone application

The solution to the problem was to buy and integrate a part from Dr Touch: DTSplashExtender. The part is not cheap but to visually improve the application startup sequence, I think this is a good solution. Here is the final implementation:

The other good thing is that the animation sequence can be made of a sequence of pictures and can be interrupted at any time to get access to the final UI more quickly. A button can also be shown at the the end of the sequence if you want to show more complete information to the user.

By the way, Dr Touch web site if full of very useful information and hints for every experience level of iPhone developers.

What do you think of it ?

Monday
Feb082010

Improving the SplashScreen on an iPhone application

As you may already know, every iPhone application uses a .PNG file that is displayed to the user when the application is loaded by the iPhone operating system. This is done in order to make the user experience nicer: instead of showing a blank screen while the application loads, a nice graphic can be displayed instead.

The duration of the display is related to the application initialization process. For some application, this process is very fast and the splash screen is not on screen for a long time. But for other, the splash screen seems to take forever to disappear (because of a slow device and maybe because of too many initializations to be done at program launch).

For uP@ssw0rdz!, the loading process duration is in the middle, not too slow but not too fast depending of the device being considered. For version 2.1, lots of code optimization was done to make the initialization process faster. And, a new animation has been added in order to make things nicer. Here is a short video of this (pay attention at the way the animation starts at the fifth second from the start of the video):

This animation is not perfect. The spotlight appears too fast.

The implementation is very simple, the Default.png file contains only the base image, a different UIImage is inserted which is the base image plus the spotlights... So two .png are involved. Here is the code for that:

// make the application UI visible!
[window addSubview:rootController.view];

// Prepare the SlashScreen to be shown
// for the animation.

SplashScreen.frame = CGRectMake(0, 20, 320, 460);
[window insertSubview:SplashScreen aboveSubview:rootController.view];
[window makeKeyAndVisible];
self.hideSplashScreen;


The problem is the appearance of the new subview, there is no fade-in effect (could find a way to implement that) and the fade-out is done by the hideSplashScreen method:

-(void)hideSplashScreen {
  [UIView beginAnimations:@"hide" context:NULL];
  [UIView setAnimationDuration:2.5f];
  [UIView setAnimationCurve:UIViewAnimationCurveLinear];
  [UIView setAnimationDelegate:self];
  SplashScreen.alpha = 0.0f;
  [UIView commitAnimations];
}

So, I don't have a lot of controls on the whole process. This is very basic stuff. If the initialization process takes X seconds on an iPod touch first generation, on the iPhone 3GS, the duration is X seconds minus "better speed factor of the 3GS". So timing this up for the 3GS will make the process too slow on the iPod touch first generation.

Is there anything better that I can implement ? How can I make the splash screen / launch process duration constant whatever device considered ? I think I found a solution to this. Stay tuned for the next part.

Thursday
Nov052009

Opening a support case at Apple - update

It's been a few days now since I opened my first support case with Apple Developer Support in order to help me a problem with my application development. We had email exchanges back and forth everyday and the guy at Apple is VERY helpful. My problem has been fixed and I'm closer to have a final 2.0 product ready to be submitted to the App Store for review. I'm a very satisfied developer.