Tag Archives: howto

Fun shadow effects using custom CALayer shadowPaths

16 Nov

Shadowed view using a rectangular shadowPath

I recently had to improve the performance of a few views that utilized CALayer-based shadows on rounded-rect UIView objects. On this particular iPad application, when the device was rotated, the views rotated quite a lot slower than we would have hoped. It wasn’t a show-stopper, but the jerky rotation animation made it look cheap and unpolished. The easiest way to have our cake, and eat it too, was to set a custom CGPath to the layer’s shadowPath property. This told UIKit to set the inside of the path to opaque, reducing the amount of work the rendering engine needed to perform.

// Add background tile
UIImage *bgImage = [UIImage imageNamed:@"embedded_bg.png"];
self.view.backgroundColor = [UIColor colorWithPatternImage:bgImage];
// Add the reference view
UIImage *image = [UIImage imageNamed:@"dccp.jpeg"];
UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
[self.view addSubview:imgView];
imgView.center = self.view.center;
imgView.layer.shadowColor = [UIColor blackColor].CGColor;
imgView.layer.shadowOpacity = 0.7f;
imgView.layer.shadowOffset = CGSizeMake(10.0f, 10.0f);
imgView.layer.shadowRadius = 5.0f;
imgView.layer.masksToBounds = NO;
UIBezierPath *path = [UIBezierPath bezierPathWithRect:imgView.bounds];
imgView.layer.shadowPath = path.CGPath;
[imgView release];

The resulting image, as you can see above, has a shadow as you’d expect. But since we’ve declared the shape the path will have, the iPad can drastically improve its rendering performance.

Through that process however, I decided to see what sort of effects I could pull off by passing in a path other than the default rectangular bounds of the layer. Since you can create any sort of path you want, I considered the different effects I could get away with by making non-rectangular paths and using them as shadows. (more…)

Localizing iOS apps using ICanLocalize.com

8 Nov

As with most things, the amount of work we as developers see when starting an iOS application is just the tip of the iceberg. There’s artwork, “About” screens, tutorial pages, icons, the app’s website, and all the marketing the app needs to get it out there. Even writing the app’s description or taking screenshots for the App Store is a time-consuming process. So anything I can do to cut down on the time needed to release my app, the better I am. Therefore when I decided to have myDrumPad translated to other languages to widen my user-base, I wanted to do make it as painless as possible.

I tried tried to have friends and family who understood foreign languages help with translations, and while they were very well intentioned it really didn’t work out in the end.  What I discovered was that there really is no substitute for hiring a trained professional.  But luckily it doesn’t have to be outrageously expensive. Read on for more.

(more…)

Dealing with MKMapView’s Google logo with translucent toolbars

12 Sep

One of the iPhone applications I’ve written, Parking Mobility, is primarily a map-based application.  Since the iPhone’s screen is so small, we want to maximize the screen real-estate while still providing navigation bars for users to interact with.  To that end, the app uses a black-translucent navbar and toolbar at the top and bottom of the screen.  In the past this has never been a problem, and most mapping applications do the same thing.  I recently submitted a huge update to the app which is a complete re-write as a 100% native Objective-C based application (all vestiges of PhoneGap having been removed).  With this latest submission though, we’ve run into problems.

Read on for more, and what I’ve done to (hopefully) get around this.

(more…)

Continuous Deployment to CPAN

18 Aug

Recently I was working on a refactor of one of my CPAN modules which, among other things, involved changing its name from Test::A8N to the specific Test::Story.  Doing so made me think about the process I usually go through when I consider releasing a CPAN module.

First, let me explain something about myself: I don’t like tedious or repetitive tasks.  I hate having to do the same thing over and over again, partly because I don’t want to waste my time, but mostly because inevitably one of the following will happen:

  1. I’ll forget a crucial step, and will screw something up;
  2. I’ll forget how to do it, and in my efforts to re-learn it I’ll screw something up;
  3. I won’t care enough to go through the effort, so something will get screwed up.

I expect you’re noticing a trend here.  Really the only reason programmers come into this profession in the first place I suspect is because we’re just so bad at doing things the normal way, we have to automate everything we’ll either do poorly, lazily, or forget to do all together.

For those of us who are programmers, many times we’re so lazy that we won’t want to do the same thing within our programs more than once, so we abstract functionality into reusable modules.  By that token the Perl community must be some of the most inventively lazy group of people, because CPAN is full of useful tidbits like that.  Getting modules to CPAN requires a contributor to actually, you know, submit their project.  And this is, in itself, a somewhat manual process.

I do all of my development in a version control repository, and I write a decent amount of unit tests to prove my functionality works.  So once I come to the decision that a set of new features is worthy of a new release, this is the process I go through:

  1. Run “perl Makefile.PL && make && make test” to verify everything runs okay;
  2. Run “make dist” to create the distribution tarball;
  3. Noticing the version number is wrong, I go in and change it in the main Perl module;
  4. After running “make dist” again, I realize I forgot to change the README;
  5. Potentially after another “make dist“, I’ll remember I’m supposed to update the Changes file to indicate what I’ve added;
  6. It’s at this point I realize that I forgot to add new documentation to cover this new feature;
  7. I run “make test” again, this time with TEST_POD=1 set to ensure my documentation checks are run;
  8. I’ll then try to remember what the command is for uploading a new CPAN module, which involves searching on CPAN for something related to “Upload”;
  9. Finding “cpan-upload“, I’ll have to look at its documentation to figure out how to use it;
  10. I run “cpan-upload“, only to realize I forgot to set my PAUSE credentials in ~/.pause.

At this point, if I’m lucky, the upload will succeed.  This process isn’t meant to be a negative reflection on CPAN, but rather on my own forgetfulness and need to automate.

Read on to find out how I managed to automate this part of my life as well.

(more…)

Building iPhone apps with Hudson, Part 2

18 Jun

I’ve already posted before on how to set up Hudson to compile and build iPhone applications, but I just had a “OMG I <3 Hudson!” moment just now, and felt I had to share it.

I do most of my mobile development literally while I’m mobile; on the train during my morning commute, from coffee shops on the weekend, or in front of the TV in the evenings when I’m winding down for the night. Because of this, I don’t have any consistent time when I’m making checkins, nor do I have the time to create builds for my beta users.

One of the iPhone apps I’m building is for a client, and because my time is limited, I want to streamline communication as much as possible, especially since I have a day job that I really like and uses 8 of my precious 24 hours per day. I don’t want to have to tell them every time new features are ready to be tested. Additionally, if I have to manually compile and send a beta build to them whenever I complete a new feature, I’ll never have enough time to actually get any work done. Add to that the fact that many mail servers will block iPhone applications for one reason or another (file size limits, misfiring antivirus filters, or any number of reasons).

So the solution I’ve come up with is an extension of my iPhone application build scripts combined with some nice plugins for Hudson. All of the above steps are completely automated away and handled for me just by checking my code into git.

  1. The first thing I did was updated my build scripts to generate an “.ipa” archive for Distribution builds containing an iTunesArtwork file, and a “.zip” archive for Release builds.
  2. My build script sets the version number of my application to the $BUILD_NUMBER of my Hudson job, so that the version is guaranteed to be unique.
  3. I added the SCP plugin to Hudson and configured a location on my web server where Hudson could upload completed builds to the website. This enables my clients to access the page to download new releases.
  4. In order to inform my clients that a new build is available, I’ve used the customizable email support in Hudson to send an email to a custom list of email addresses when a successful build is completed. In this email I include a link to the uploaded IPA so they can easily download the beta archive.
  5. So that I don’t have to go through the trouble of describing what changes I made, I use the $CHANGES_SINCE_LAST_SUCCESS variable in my custom email template that lists all the commit messages I’d submitted to git that were included in this build.
  6. For good measure, I SCP to the website a copy of the “.mobileprovision” certificate file that was used to build the application, so the beta tester can add it to iTunes if the contents have changed.

The result of all this work is that I can work wherever I am, continually committing changes into git. When I’m ready to cut a new build, I submit my changes to github where a webhook script will notify Hudson that changes have been made. Hudson checks out my changes, builds them on my Mac Mini at home, SCP’s the resulting archive up to my web server, and notifies my beta testers that a new archive is available and what changes they should keep an eye out for.

For a copy of the build scripts and configuration I use inside my projects, take a look here:

This assumes there’s a file in the build user’s home directory called “.build_password” that contains the password used to unlock your keychain. Run “chmod 600″ on that file in order to make it hidden to anyone else on your system.  And make sure you check in the “.mobileprovision” files your XCode project file references.  If you change your certificates, you’ll need to copy the updated mobileprovision files from your “Library/MobileDevice/Provisioning Profiles” directory.

So you can see why I’m excited about this.  I hope you are too.

Telling your user that a PhoneGap application is busy

26 Oct

Plenty of times in applications, especially on mobile devices, you just need to tell your users to hold their horses and wait while your application processes something in the background.  Maybe you need to query some data from a remote server, save a file to disk, or maybe you just need to do some number crunching.  Whatever the reason, you don’t want your user to think the program has crashed if you don’t give them some sort of visual feedback that you’re busy and they just have to wait a few seconds.

PhoneGap provides a few methods to handle just this task. There’s four methods within the Notification class that are of interest.

  1. navigator.notification.loadingStart()
  2. navigator.notification.loadingStop()
  3. navigator.notification.activityStart()
  4. navigator.notification.activityStop()

Modal loading messages

Modal loading indicator

Modal loading indicator

The easiest approach to take when making your users wait is to show a modal loading dialog, one that doesn’t let the user interact with the application until you’re done.  There’s a lot less for you, as a developer, to manage when the user isn’t allowed to poke around on buttons when you’re updating the display.  Asynchronous operations are a lot simpler when you’re in control.

The loadingStart() and loadingStop() methods do just this.  They put up a modal semi-transparent layer over top of your application, with a “Loading..” spinner message. You simply call the first method when your application is about to do something, and when it finishes you call the second.

Here’s an example of how to use it.  This will load a remote HTML document and place its contents into a node in your PhoneGap application.

Not only does this make it easier to integrate external content into your PhoneGap application, but it guarantees your user is informed that it’s actively working. As a final bonus, if your external web site doesn’t respond, or if the user doesn’t have an Internet connection, the modal loading screen will close after a timeout.

Asynchronous loading messages

Asyncronous activity loading indicator

Asyncronous activity loading indicator

Sometimes you want to tell your user that the application is busy, but you still want to continue using the app anyway.  If your app doesn’t turn off the top statusbar (where the time, reception, and battery status is displayed), you can control the busy indicator from within PhoneGap.  Just like the above example, you just have to call the appropriate PhoneGap JavaScript methods.  In this case, just update the above example with these messages:

navigator.notification.activityStart();
// Do something that might take a while...
navigator.notification.activityStop();

How to use the native Alert dialog in PhoneGap

19 Oct

PhoneGap's custom alert notification is nicely customizable

PhoneGap's custom alert notification is nicely customizable

An important part to any application is issuing a simple alert to your user. Whether it’s to tell them about an error that just occurred, or if you need to ask them a simple question, giving a message to your user is about the most basic part of any app.

Sadly, when you try to rely on the ever faithful “alert()” function in JavaScript inside a PhoneGap application, you’ll notice the alert box it shows is titled with a very unprofessional “index.html” across the top. Not only does it make it obvious that the app they’re interacting with is actually HTML-based, but you can’t convey the importance of one message or another with a title. Most people only ever read the title anyway, so in order to provide this capability to your application, PhoneGap has an answer for this problem.

Inside PhoneGap there’s a class called “Notification” which is used for, well, sending notifications to your user. And, by calling:

navigator.notification.alert(
  message,
  title,
  buttons...,
  options);

Everything, except for the message, is optional. The more arguments you provide, the more you can customize the alert box. For instance, if you don’t supply a button label, one single “OK” button will be created. Want to ask a Yes/No question? Simply pass two labels for their respective button names.

Like other functions in PhoneGap, the alert notification can be passed an “options” object that allows you to give it more information, such as an onClick callback.

That example shows how to ask your user what to do in the event of an Internet connection problem.  You’ll notice that I’ve decided to pass two button labels.  In the onClick callback function I supplied in my options argument, I’m checking the “buttonIndex” variable it passes.  This tells your function which button was pressed.  If you want more than 2 buttons, just list multiple labels and it will show as many as can fit on the screen.

A very simple function, but invaluable as a developer resource.  And, more importantly, a very easy and professional way to get feedback from your user.

How to use the ActionSheet in PhoneGap

16 Oct

The ActionSheet is a handy control on the iPhone, and is a very intuitive way of getting a multiple-choice answer from a user in a modal but unobtrusive way.

Using it in PhoneGap makes interacting with your user easy, while keeping the display responsive. And as an added bonus, you don’t need to update any HTML or CSS to get the buttons to look right. The native iPhone codebase handles it for you.

So the question is, how do you use it effectively? As most Web2.0-style developers are aware, the only sensible way to develop flexible applications that don’t bog down the browser is to make your applications behave asynchronously, and make use of callback functions to get feedback from external systems (HTTP requests, users, etc). The ActionSheet on PhoneGap is no different.

The ActionSheet is grouped into the PhoneGap “Dialog” class, and is called like so:

dialog.openButtonDialog(title, buttons..., options);

The title property lets you specify the label to show at the top of the ActionSheet. If you don’t want a title, then simply pass in a null value.

The list of buttons is specified as a series of objects, which I’ll describe below.

Finally, the options let you customize how the ActionSheet is displayed (via the “style” property) and lets you set an onClick handler for the entire ActionSheet.

The example above illustrates several options of the ActionSheet PhoneGap control.

  1. On a per-button basis you can specify your own onClick callback which will be run when that button is pressed.
  2. A global onClick handler can be specified in the openButtonDialog options argument, which will get called no matter what button is pressed.
  3. You can choose what the appearance of the dialog should be (currently only “opaque” and “translucent” are supported)
  4. A button requires a label property, but you can optionally specify a “type” property (can be “normal”, “cancel” or “destroy”).

The callback functions are simply called with two arguments, the index of the button being clicked, and the label of the button the user clicked on.  So if it’s easier for you to work with array indexes, or with text labels, you can easily find out which button was pressed and when.

So go ahead and try out the ActionSheet control.  Either you can use my latest release in my branch of PhoneGap, or you can use these more advanced features once my changes have been merged in with the official branch.