Monday, December 5, 2011

Setting Up a Folder Action


The Automator application on OS X gives a good drag-and-drop way to have the computer take over some repetitive tasks for us. Things that Automator can be good for are:

  •  combine a bunch of PDFs into a single PDF
  • rename a whole bunch of files
  • run a script (bash/ruby/php)
  • manipulate some images (resize or watermark)


If you think you will actively be working with files (dragging them around) then set up an Application automation. If some other task might be creating the files you are starting with then you might want to set up a folder action. In other systems the folder action is called a "hot folder". This quick tutorial is going to set up a folder action to take any file or set of files I dump into the folder and then add a timestamp to the filename and move the item to a folder on my hard drive called "Finished".

First we will open Automator and select a New workflow from the File menu. We are going to make a workflow of type "Folder Action" so we select the proper icon and click the "Choose" button.

By choosing a folder action, we are asking Automator to watch the folder at all times, and whenever we add any file, group of files or folders to the folder, we want the workflow to begin.

The first thing Automator will want is an answer to "Folder Action Receives files and folders added to". We need to choose what folder is going to have this action attached to it. For the purposes of this demo, we are going to create a new folder called "StampTasks" and place it on the desktop.

The next step is to add the timestamp to each file that gets dropped into the folder. In the Automator, there is a library. The library has two types of actions: those supplied by the system and those supplied by third party applications. Pixelmator gets a shout out here for some of the really useful automator actions they have supplied.

For this tutorial, we are just going to use the action in "Files and Folders" called "Rename Finder Items". We do this by just dragging the Action from the list of actions to the main workflow window. When we first drag the action, we will get a dialogue box asking us if we want to work on the original files or if we want to make duplicates of the files and work on those.
For my purposes, I don't mind working on the originals, so I click Don't Add for this tutorial. Now we are presented with the second step in our workflow. For renaming purposes, Automator provides us with a few different choices for how we want to rename our files. 

Today we are just going to "Add Date or Time" and using the drop down menus I am going to insert the current date after the name of my files.

Now we need another action to move these files out of the folder and place them into their final resting place. So I use the "Move Finder Items" and then navigate to the folder I want to place the items into. "Move Finder Items" can be a little confusing, but basically it is saying "take the file that you did an operation on in the previous step and move it".

Finally, just to show off we can add a "Show Growl Notification" (this action is under Utilities if you have Growl installed). Here is what the final workflow looks like.



At this point you may be excited to run your new folder action but you will see that the "Run" button gives you an error. This is because the workflow starts when you drop a file into the folder, so we need to save the workflow first (NB: with Lion, I have gotten lazy about saving things, but if you don't explicitly save, Lion will happily not save a workflow and it doesn't give you the "Save As..." or other indication that it didn't save). It just won't run your workflow and you will say bad words.

If you have created the workflow and saved it, you should now be able to drop a file into the "StampTasks" folder and wait a few seconds and see it appear in the "Finished" folder with a Growl message. Here is a link to a zip copy of the workflow I created for this tutorial. In general, Automator will place files in the ~/Library/Workflows/Applications directory. (NB: In Lion I notice that the Library folder for the user is not invisible, so you may need to use "Go to Folder" from the "Go" menu in Finder to get at it.

Gotchas:
The biggest issue with using the Automator is that debug info and errors are hard to work with. For instance, using the working tutorial above, delete the "Finished" folder. Then when you run the workflow you will get no error, but it won't run either.

Working with Scripts:
Any bash or ruby script can be run in automator using the Run Shell Script command. By default you can run shell scripts in your favorite flavor of sh as well as perl, python or ruby. The shell scripts should be expecting to get the files or text they are to work with just as if they were set up to get things from the command line. The shell script will be run once for each file in the folder.

Tuesday, November 8, 2011

Devices for Testing iOS Software

For the next few months at least it's going to be a pain to test in iOS. Recently I had to test an app on 4 different devices and it behaved differently on all four. So, here is the set-up I used to try to get the best coverage.

Old Devices
The oldest devices I'm willing to support (or that my clients ask to support) are running iOS 3.1.3. These are second generation iPod touches as well as iPhone 3G devices. Thankfully, these are the last devices are the last ones that don't do OS signing with Apple, so it is pretty trivial to upgrade them to 4.2.1 (the highest OS they support) and then back to 3.1.3 (a common OS because it runs faster). For maximum coverage, I have one device at one OS version and one at the other. Switching OS versions is easy but time consuming. I have an iPod Touch and an iPhone 3G for this testing. I decide which one to set at which version depending on if I need the camera for my app or not. These devices require armv6 code.

Less Old Devices
Apple is currently selling iOS 5 installed on iPhone 3GS, iPhone 4 and iPhone 4S. All of these devices are armv7 So, I'm treating this hardware as interchangeable for now. I have an iPhone 4 running 4.3.5 and I have an iPhone 3GS and and iPhone 4 both running iOS 5. Apple has made it really hard to upgrade/downgrade without jailbreaking, so I have to have big stickers on my 4.3.5 device to make sure I never upgrade it by accident.

iPad
I have an iPad (1) and and iPad2 that are both running iOS 5. Because the iPad is a newish device, I have assumed that everyone has upgraded or is upgrading soon away from iOS 3.2. I test with 4.3 in the simulator and test on the devices in 5.

What else?
In my experience, the biggest change as far as the OS breaking things happened between iOS 4.2 and 4.3 which corresponds to the 3G devices and the 3GS and above. Apple made lots of changes to the video, and graphics libraries during that time. Because the 3G and the older iPod Touches only go up to 4.2.1 (and even then don't support multi-tasking) we need to keep testing with those devices for a while. If an application doesn't require the new features in the newer OS'es then it seems like a poor decision to cut out the older devices, those people still have iTunes accounts and can still give us money.

My Wish List
Google has a really nice chart of what OS versions in what volume are hitting its App Store each week. This can help a developer make good guesses about what OS should be the minimum. Apple should be able to provide this data. I wish they would. It's one thing for me to gather data about my current customers (which I can do using Flurry or similar analytics) but that information is only about my small part of the customer base, not about the entire population.

Tuesday, October 25, 2011

iOS 5 Support for dismissModalViewControllerAnimated

Fixed an odd bug today and submitted v1.3 of Caroline's Cat Game to the store. Turns out that calling dismissModalViewControllerAnimated: for the [self parentViewController] basically stopped doing anything. When Apple makes changes that cause crashes that is bad, but at least we get some kind of alert. This just makes a button stop doing anything. No crash, no error, no nothing.

Anyway, if you are here because your calls to parentViewController have stopped working, here is the code we are now using. It appears that we need to use "presentingViewController" as well as a new call to dismissViewcontrollerAnimated. This all seems to be related to storyboards in iOS 5. Here is a link to the updated UIViewController documentation that talks about parentViewController and presentingViewController and the new dismissViewControllerAnimated. Right here below, is how we have set up our button to respond to being clicked. In the old days (last month) the method just had the   [[self parentViewControllerdismissModalViewControllerAnimated:YES] line but we have to add a little more now.


    if ([[self parentViewController] respondsToSelector:@selector(dismissModalViewControllerAnimated:)]){
        
        [[self parentViewController] dismissModalViewControllerAnimated:YES];
        
    } else {
   
        [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
    }


We have wrapped the whole call into an if statement so that we can still use the old way when on an older phone. The respondsToSelector: test is a good way to deal with using old and new code together. Trying to test for a specific version of iOS by name is pretty brittle; always use the respondsTo method instead.

Friday, October 21, 2011

Setting Up Xcode to Support Old iPhones

The iPhones from v1 to v3G all use the armv6 architecture
The iPhone 3GS and above all use the armv7 architecture (this is why it is not a really big deal that Apple has decided to continue to sell the iPhone 3GS)

The phones that run the armv6 are mostly on iOS 3.1.3. It is possible to pus 4.2.1 on an iPhone 3 but it runs so….very…..slowly….that most people have downgraded back to 3.1.3 or else bought a new phone. The 3GS runs iOS 4.x and 5.x pretty well so there is no reason for people with a 3GS or above not to be on 4x or 5x. The 3GS had some issues with iOS 4.0 but those speed issues have been addressed and any 3GS you purchase today will have IOS 5 on it.

As is their general theme, Apple hates supporting old things so the defaults in Xcode 4 (and 4.2 which is the current version) assume that everyone is running iOS5 and that they have a 3GS or better device. That is a reason the simulator only has options for 4.3 and 5.0 software. If you read this article from Apple Insider you will get a nice graphic showing how hard Apple is pushing iOS 5 and on what devices it runs.

To make your Xcode compile code for an old iPhone you have to do two things:
In Build Settings for your target, change the "Compiler for C/C++/Objective-C to LLVM GCC 4.2 (this is not the default)
In Build Settings for your target, change the "Architectures" from "Standard (arm7)" to "armv6 armv7"

You should also check these two settings since Xcode is going to want to have the Deployment Target be the latest version of the OS by default.
In Build Settings for your target, make sure that "iOS Deployment Target" is set to "iOS 3.0" or whatever the minimum you will support is
In Build Settings for your target, make sure that "Base SDK" is set to "Latest iOS (iOS 5.0)"

Now, you should be able to install and compile things on the old phones. The above settings are for ALL projects you create where you want to support older devices.

Update: Others are having this problem and posting similar fixes. I think I like this fix for the armv6 issue over at Retro Dreamer better.

Thursday, August 25, 2011

Supporting TextExpander in My Application

Overview:

With version 2.0, the Massage Therapist Notebook now supports TextExpander snippets. A great deal of information about a session can be recorded just by dragging stones onto various parts of the body images. However, notes are handy as well. Because of the way that the iPad deals with special characters (like colons and semi colons that are hidden on an auxiliary keyboard) we realized that entering a lot of notes was going to be a big problem. Additionally, when customers want to create an expansive narrative either for themselves or for an insurance claim, the MTN would stand in the way rather than being helpful.

For the first version, we added a single text macro of .SOAP. that will create the text of
S:
O:
A:
P:
in any note field. This boilerplate text is to help those practitioners who use the SOAP method to document their sessions. However, the CARE method is also in use and in other languages, neither of these is used widely. We realized that we needed a way for anyone to be able to create a series of sentences or paragraphs that they could call up from the application.

That just happens to be the primary function of the TextExpander application.

Setting up TextExpander:
On a desktop computer it is simple to have one program that makes itself available to all other programs. However, on an iOS device (like an iPad) this is much more difficult. The application providing the service has to be written in a particular way and any application that wants to consume the service must also be written in a particular way. Fortunately, to set up TextExpander for sharing a customer just needs to change one setting in TextExpander. They need to turn "Share Snippets" on.
The Massage Therapist Notebook is always checking to see if TextExpander is running. If Text Expander is running then the Massage Therapist Notebook lets it monitor all of the notes as they are typed. When a macro snippet is typed then TextExpander will immediately replace it and even provide a nice whooshing sound to let you know a change has been made (it would be nice if autocorrect did something like this).


Making a snippet:
To make a snippet in TextExpander, we just need to decide on a character sequence we will type and the words that will replace the sequence. Here we have made a snippet in TextExpander to describe neck injuries. For longer paragraphs and phrases, TextExpander supports copying and pasting from other locations. For those people who have the desktop version snippets can be created and shared even faster. If you create a lot of snippets, it would be wise to create a naming convention so that you don't accidentally type one when you don't mean to and so that you can remember all of them.

Adding the snippet to a Note:
Type the Macro
For our example snippet of nkinj1 we add the snippet just by typing. As soon as we type the last character of the macro name (as soon as we type the 1) we hear the whooshing and the new phrase appears. Woosh!
Woosh!
Using the SDK:
Following along with the sample application in the SDK that Smile! provides couldn't have been easier. We simply added a few calls to our delegates for the note taking screens. We were even able to preserve our little .SOAP. macro because as soon as TextExpander does its thing it hands control right back to our program. We are so excited about this integration. We hope our customers find it as valuable as we think they will.

Wednesday, August 24, 2011

Massage Therapist Notebook 2.0 Submitted for Review

We have submitted the latest version of the Massage Therapist Notebook to the store for review. Hopefully it will get approved without requiring any major changes.

There are three big, new features of this app. The first is support for Text Expander. We are excited about this and the SDK that Smile provided made this really easy. In essence, Text Expander will let you type out words, sentences or even whole paragraphs and then assign those to a set of keystrokes.

In the first versions of the app we rolled our own macro (go ahead and type .soap. into any of the session notes, stone notes or clients notes). However, we realized that this was going to be a never ending issue. Thankfully we found Text Expander.

The next is a change in how we draw the stones. When a stone has an associated note (do a long press on any stone to add a note) it will now get a little halo instead of the stripes icon. We have done this because we are working on setting up a symbol editor in a future version so the therapist can add any symbol they desire to the stones. We are also considering letting a therapist edit the colors of the stones themselves, but one thing at a time. We have also added enough new colors so that there is more variety.

We have added a PDF export of any session as our final big feature. This will create a pdf with the body figures and their stones, all of the stone notes and session notes as well as any client notes. This was by far the hardest new feature to add. Once the PDF is created it attaches itself to an email. In future versions we will probably have to rework this part the most so that it is more usable.

There were some other minor bug fixes and UI enhancements. The most common question we got over these past few months was "how do I delete clients". The functionality has always been there but now we've made it more obvious.

What didn't make it into this version:
Client intake forms. This is going to take some thought since there are lots of different ways to make intake forms and lots and lots of questions that might be specific to a single practice.
Multiple body figures. We want to have the ability to have just hands or feet and different body figures with pressure points and other markings. It just wasn't ready.
Stone editor. As mentioned above, we are shooting to have more customization over the stones.
Universal (iPhone) version. We want the product to settle down just a little before we go adding this.

Wednesday, July 27, 2011

Chakras in Massage

Some of our customers of the Massage Therapist notebook use chakras in their practice. For them, the three stones are not enough to represent all of the different chakras as well as other interest points. We are incorporating these new stones
The New stones for the Massage Therapist Notebook
into the app for the next release. In order to represent the chakras correctly we need to have each of the seven colors of the rainbow. We have enjoyed finding lots of different textures to use for the stones themselves. We decided to look for textures from nature, so butterfly wings, flower petals, moss, and fruit images are used for many of the new stones.