MKNetworkKit for iOS Network caching

Recently I’ve been working with several apps from the same client that all rely on regular posts to their web server to post various data objects from their app. Under a minimal load these network operations work properly where the app sends a data post and waits for a response back.

Just recently the app was put under less than minimal conditions however and the app came to a halt. Due to circumstances beyond their control the wifi and cell network they were using at an event with over 3000 users began to cripple. Since their app relied on immediate responses from the server the app got stuck waiting sometimes minutes for a response that usually took milliseconds.

Our solution was twofold:

First we created a local in-app cache of the data the app needed from the server. Even though the server data is regularly updated it was a good enough compromise in their setting to update the local copy on an hourly basis.

Second we implanted the freezable operation concept from MKNetworkKit. Even though we had a local copy of the data we still needed to send the user actions to the server for processing. So our lookups happen locally but the server still needed to know the action taken with the data.

With freezable operations we could immediately process the action locally and queue the operation without needing a server response. If the network is operational the post to the server happens quickly although decoupled from the lookup now. That alone sped up the app. But the real improvement came with the freezable operation during an offline situation. We queued the operation as usual and just kept on going with more local data actions. Whenever the network comes back online the frozen operations are automatically processed by MKNetworkKit. The server gets the action data and all is well but with. I performance degradation.

Definitely a vast improvement to the app

The screen utility is your friend! – aka upgrading ssh remotely

This is an “oldie but a goodie” for some of you, but it always bears a reminder.

If you try to upgrade your ssh server remotely it will likely hang when you go to restart the service after upgrading.

A client recently needed chroot sftp capabilities on their server and their OpenSSH server was out of date. They were on version 4.3 and the chroot sftp capabilities were added in 4.4. I upgraded e machine to version 5.8 today. It has been a while since I’ve needed to do this remotely and I almost restarted sshd in my ssh session when I remembered I would likely have my session disconnect during the restart and the start process would fail.

Definitely not what you want for your customer!

In comes in the wonderful screen utility. The screen program lets you start a terminal session within your session that won’t get killed when sshd restarts. I just installed screen, typed screen and entered my new session-within-a-session. Now I restarted openssh and it killed my remote session, the screen session survived and completed the openssh restart.

I was able to connect right back in to the new version of the sshd server with no issues.

Not So Fast! Adobe Flex Still Alive?

I haven’t touched Flex projects in a couple of years now. Once the iPad came out all my Flex clients dropped Adobe Flash. We moved lots of code to HTML5 in the past several years.

For all that HTML5 has to offer, however, I have often missed some of the beauty found in the Flex environment. So recently when a new client asked me to take on some legacy Flex code for updates I began digging back into Flex.

To my surprise I find myself as happy as ever to code in ActionScript and Flex. I am also quite pleased to find how well the latest AIR platform supports iOS. It may just happen that my next iOS app will be written in Flex instead of in Objective-C or in HTML5 with PhoneGap.

Sounds fun!

Vagrant Disk Trashed When Upgrading VirtualBox Too Far

User beware… If you upgrade your VirtualBox too far ahead of the guest additions installed in Vagrant then you can end up with an instability that will trash your disks in the vagrant box and cause the file system to go read only.

I kept having readonly filesystem problems and they were getting more and more frequent. After combing the vagrant and virtualbox forums I saw some hints that it might be related to Guest Additions being too far out of date with the main VirtualBox version. After following the instructions here to get my guest additions up to date I’ve had no further trouble with a readonly file system.

Automator Workflow to Reduce Large PDF Files

When I worked in the Linux world I used a variety of command line tools to help reduce the size of large PDF files. In the Mac OSX world I started looking at converting some of my same scripts over to run on OS X. There were several tools I needed to install via MacPorts and as I started that process I realized there was probably a simpler way already built into OS X. Sure enough, there is: Automator.

To all you long time Apple users Automator is old news, but it was new to me. Here is how I created an Automator workflow (and then app) to reduce PDF large files down to size by shrinking the images inside the PDF.

Open Automator and choose to create a new application.
From the Library choose PDFs.
Drag the item labeled “Apply Quartz Filter to PDF Documents” to the workflow area.

I could choose the filter called “Reduce File Size” but I want to make some adjustments to it and the default filter is locked so click the Advanced options and from the list option-click (or two finger tap) the Reduce File Size filter and choose Duplicate.

Now spin down your copy of the filter and adjust the Image Sampling and Image Compression settings. For sampling I used 50% scale, 1024 max pixels, 128 min pixels and High quality. For compression I used JPEG mode and set the quality a few notches below Max.

Now in the filter dropdown at the top choose your Reduce File Size Copy filter.

I want the PDF to be opened after reduction so go to your library and choose Files and Folders and drag over the Open Finder Items action.

Make sure Open with is set to “Default Application”.

Now save your workflow and put your compiled app on your desktop or somewhere handy. Any time you need to reduce a PDF drop it on the app icon and your PDF will be reduced and opened in Preview.

PhoneGap + ChildBrowser – Opening all non-app links in ChildBrowser

I’ve been working on a PhoneGap project with iPad as the target. Most of the app runs from an external site so after presenting local files to handle the login form and authentication the main webview then shifts to an external site where the rest of the code runs.

We are using ChildBrowser to handle showing images and PDF files from the external site so that we can don’t have to include a navigation bar in our app. The ChildBrowser plugin helps us view those files without getting locked out of the original app. That’s just the background. Now we have a new problem. Many pages in this app link to external sites that are not part of the main application. We needed ChildBrowser to handle all non-app site requests automatically so that external sites would open in the popup and not replace the view in the main UIWebView of PhoneGap. Here is how we solved it:

We started with the PhoneGap.plist preferences file. In the ExternalHosts array within that plist we added all the possible host combinations that our app considers as local to the app. This app has about seven url host variants that could be used within the app so all of those should open in the main WebView. Any host not listed in ExternalHosts should open in the ChildBrowser. Keep in mind that to allow all external sites to open we still had to put * as an entry in ExternalHosts but this doesn’t affect the logic below.

In AppDelegate.m didFinishLaunchingWithOptions method I added this logic to load the PhoneGap.plist into a Dictionary and read the ExternalHosts into an array. If anyone can tell me this is already loaded somewhere and I could have skipped this step let me know in the comments:

NSDictionary *phoneGapPrefs = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"PhoneGap" ofType:@"plist"]];
self.internalUrls = [[NSArray alloc] initWithArray:[phoneGapPrefs objectForKey:@"ExternalHosts"]];

I’m assuming you know how to create the internalUrls variable as an instance variable in AppDelegate.h. Now I have an array of all my internal host names so that any requests that don’t match that are loaded in ChildBrowser. Now we proceed down to the shouldStartLoadWithRequest method where I add this logic to check if we’re loading an external site (starts with http) and check if that site is part of our internalUrls array.

if ([[url scheme] isEqualToString:@"http"] || [[url scheme] isEqualToString:@"https"]) {
    //This code will open any url that is not in the PhoneGap whitelist in Child Browser
    if (![m3Urls containsObject:[url host]])
        [theWebView sizeToFit];
        ChildBrowserViewController* childBrowser = [ [ ChildBrowserViewController alloc ] initWithScale:FALSE ];
        childBrowser.modalPresentationStyle = UIModalPresentationFormSheet;
        childBrowser.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;   
        [super.viewController presentModalViewController:childBrowser animated:YES ];   
        NSString* urlString=[NSString stringWithFormat:@"%@",[url absoluteString]]; 
        [childBrowser loadURL:urlString];
        [childBrowser release];
        return NO;      
    return YES;

Now all urls that start with http or https as the scheme and are not in the ExternalHosts I’ve listed are considered external to our app and are loaded in ChildBrowser. At this point you might tell me that since I’m listing * as a valid ExternalHost I don’t need to list all the site-specific urls and you’d be correct as far as avoiding the whitelist. During initial development I didn’t even anticipate opening non-site urls so all I wanted to list were the site-specific urls for this app. Later on I added the * for allowing any url, but realize that listing all my internal app urls provided an easy way to accomplish my need to determine which urls were for my app and which were references to non-app sites.

Find parent form in jQuery

Needed to find the parent form of a form element. This answer on StackOverflow gave me the right answer.

Problem with jQuery-UI Draggable and Form fields – Solved!

I’ve been using the Draggable functionality of jQuery-UI on a project and ran into a new problem. I needed to add form fields like SELECT and INPUT in my draggable div. Unfortunately, since my container itself is draggable it prevents clicking anything inside the container from being selected so I can’t choose items from the dropdown or focus on the input box to type text.

The solution is rather simple. Just add the appropriate selectors in the cancel option of Draggable. Actually, in my case I’ve migrated to Sortable so I added it there. Now my cancel option looks like: “select, input”. Works like a champ!

Help! Where’s My App Switcher Gesture in Lion?!

I rarely upgrade any OS when it is first released. This was always my practice with Windows, then Linux and now with OS X. So when Lion was released back in the Summer I passed on the chance to be first in line. Then 10.7.1 came out and I still waited. But with the arrival of iOS 5 and iCloud it was time to upgrade in order to take advantage of PhotoStream among other things.

I’m a huge fan of trackpad gestures and so I was pretty happy that Lion expanded the use of gestures, but I was shocked that my most often used gesture from Snow Leopard, the four finger swipe to open the Cmd-Tab application switcher, was gone. Cmd-Tab still opens the old application switcher but the familiar four finger swipe is gone and now there is a three finger swipe that invokes a switch between the new Lion desktops and full screen apps. So unless I run all my apps full screen, the switcher just goes between Dashboard and the main Desktop. Not what I want at all!

After half a week of frustration and searching for a solution I found BetterTouchTool. BTT gives me back everything I lost and more! I left the three-finger swipe alone and now have a four-finger swipe that opens up my long lost Application Switcher. BTT doesn’t stop there, however. It has an advanced application switcher where I can start the swipe and leave one finger on the pad and while still touching the pad, move the cursor to my desired application and then let go of the pad. With a few seconds of training my brain, I now switch applications faster than I ever did under Snow Leopard.

If you’re longing for more out of your trackpad or magic mouse, you must give BetterTouchTool a try. At the very least it restores lost functionality to Lion, but I think you’ll find it adds even more possibilities to gesturing than you had previously imagined.

DropBox vs SugarSync – Or why I’m keeping DropBox

I’ve used DropBox for quite some time now and loved it. When I needed more default storage, however, a friend pointed me in the direction of SugarSync. SugarSync offers a range of different features, but my clear favorite is the ability to flag any folder on my machine as a sync folder. No longer do I have to put my sync files in the DropBox folder, I can sync any of my standard folders and leave them in place.

SugarSync also maintains a distinction between which files came from which of my computers or mobile devices so if I want files specifically from my laptop instead of my desktop the mobile clients show that distinction.

Combine that with a base storage allocation of 5GB and SugarSync looks like the clear winner. Almost.

After two months of using SugarSync I still find myself using DropBox far more often in my day to day routine and there is one simple reason: mobile integration. It seems every app that I care about on my iPad and iPhone allows for DropBox interaction. If I want to work in Office2HD for example or PrintCentral or a myriad of other apps, all of my files have to be in DropBox. For reasons I haven’t explored, SugarSync does not have built-in support in any of the apps I use.

So while it is wonderful to have more storage and sync any folder on my machine, when I want to edit files in my mobile devices DropBox is the go to storage medium. Thus here I am two months later still using DropBox as my mobile storage medium and SugarSync as my cloud backup medium.

Maybe iCloud will change all that but somehow I still think DropBox is going to be my the storage medium of choice for some time to come. We’ll see.