Deploying a Read/Write Resources with your iPhone Application

iPhone development has been a great experience but that does not mean it has not been without its challenges. For instance, if you are planning on saving some sort of dynamic content in your application, you will quickly find that it is not simply a matter of discovering where your application is being stored and writing some files in there.  It is a little bit more involved than that.  In order to help those who come after, we thought it would be worthwhile to share some of our findings.

I think the first thing to realize is that when your application is deployed onto your iPhone/iPod/Simulator you are deploying a complete package. This means that the contents, i.e your code, resources, database and anything else that might be part of your deployment bundle are uniquely signed using your developer’s key which verifies that everything you intended to be in there is there and nothing else. This is a very important concept from a security standpoint and it allows the target device to verify the validity of the bundle to ensure that your application has not been compromised. Now that we have stated that, it’s pretty obvious that it will be impossible to change the deployed project. This doesn’t mean that Apple didn’t think of this inevitability.

The first step to looking into this deployment will be looking at the target deployed file system. The easy way to find this is to log the applications bundle path in the applicationDidFinishLoading method on the appDelegate. You can do this with the following code:

NSLog(@”Application Directory: %@”, NSHomeDirectory());

The output (in the console) for this will show you where you can find the file system. I usually just copy and paste this into a terminal window and jump right to it (just make sure to wrap the directory name in double quotation marks).

If you navigate tot this directory you will see your application (yourapp.app) which is a directory containing all of your code and resources and a Documents and a Library directory. That Documents directory is where our dynamic content will reside.

This seems straightforward enough, just put what we need in the directory and away we go, right? Well not so quick cowboy, there is no idea of an installer that executes when your application downloads. This means we are going to have to figure out how to copy the files into the Documents directory the first time the application loads.

Over here at BeefyApps, we developed this little snippet of code to handle this initial load of data.

-(void)initializeDocumentDirectory
{

NSFileManager *manager = [NSFileManager defaultManager];
NSArray *templateDir = [manager directoryContentsAtPath:[NSString stringWithFormat:@"%@/Documents", [[NSBundle mainBundle] bundlePath]]];

for (id file in templateDir) {

if ([manager fileExistsAtPath:[NSString stringWithFormat:@"%@/Documents/%@", NSHomeDirectory(), file]])

continue;

NSString *srcPath = [NSString stringWithFormat:@"%@/Documents/%@", [[NSBundle mainBundle] bundlePath], file];
NSString *dstPath = [NSString stringWithFormat:@"%@/Documents/%@", NSHomeDirectory(), file];

NSError *error;
[manager copyItemAtPath:srcPath toPath:dstPath error:&error];

}

}

So the code above simply takes a look inside of the bundle, navigated to via the [[NSBundle mainBundle] bundlePath] command. The result of this call will provide you with the string location of the applications executing bundle directory. For the purposes of this code we have a Documents directory which resides inside of the bundle path. We then take the contents of that directory and conditionally copy it file by file into the writable Documents directory.

Pretty simple solution really. I think where this gets interesting is when we start to consider the ramifications for updating your application. I’ll leave that exercise up to the reader at this time though.

Tags: , , , , ,

BeefyBoard: iPhone Soundboard Ready For iPhone OS 3.0

With the new iPhone OS 3.0 being released today, we here at BeefyApps have been busy updating BeefyBoard: iPhone Soundboard for use with OS 3.0. We’ve found that some of the sound features that worked in OS 2.2.1 were no longer compatible with OS 3.0, specifically recording a sound to the phone and then switching back to playback.

With a little bit of work we’ve fixed these problems and have submitted the new app for approval. The new version should be available to download early next week if the approval process goes smoothly. We’ve also taken the opportunity to add more features to BeefyBoard that will make it the best iPhone Soundboard out there.

What this means to existing users of BeefyBoard and those that purchase it within the next few days is that if you upgrade to OS 3.0, some of the functionality of the app will be broken until you update to the new version of BeefyBoard (when it becomes available on iTunes).

New Features in Version 1.1

  • Added Board Ratings
  • Added Board Comments
  • Added Skin Ratings
  • Added Skin Comments
  • Added Skin Affinity
  • Added Settings Controls
    • Enable/Disable skin affinity
    • Shake sensitivity
  • Added Upload Progress Bar
  • Stop Recording By Pressing Any Button
  • OS 3.0 Compatibility fixes
Tags: , ,

BeefyBoard Soundboard and Skin Listings

We at BeefyApps are proud to announce that you can now browse the list of skins and soundboards that users have submitted, online! This will allow you to see the comments and ratings that will be available in our upcoming release. You can view the skins here: http://sounds.beefyapps.com/skin/list and the soundboard list is here: http://sounds.beefyapps.com/board/list.

Check it out and let us know what you think.

Tags: , , , , ,

Star Rating Slider

I remember looking at Apple’s iTunes rating slider and thinking to myself, that will be perfect to integrate into BeefyBoard: The iPhone Soundboard for rating soundboards and skins alike.  Imagine my dismay upon combing through the SDK and coming up empty handed.  Not to be deterred though, I managed to recreate something similar to apple’s slider using a couple images and the base UISlider implementation that Apple provides.

sliderblog1

Apple’s UISlider component is made up of two images one for the left, which I like to call the filled side, and another image for the right, or the empty side.  Apple deals with these images by using some stretchable images with caps and this lets them resize the slider to their heart’s content.  We however do not really have that luxury.

Gotcha #1: The left and right images need to be the same size and you need to account for the frame padding that Apple adds in as part of the component.  On the slider that I worked with, my two images were 250px wide but my slider control had to be 254px wide in order to display properly.  You will notice if you start playing with the size that it will mess up your image if you get this wrong.

Gotcha #2: The thumb image that you choose will affect the size and the position of the two images and where they meet.  Even though you might have figured out how to get the images to line up, if you are using a thumb control image the UISlider will adjust the size of the image to take this into account.  For instance, if you make your thumb image 50px then 50 px will be added to the width of the control to take into account the width of the thumb on either side of the slider.

Now that we have talked about all the sizing problems we should be great right?  Not yet, we still need to worry about the way that you control the slider.  Between the 2.1 and 2.2 releases of the iPhone SDK the behaviour has changed for the touch sensitivity of the UISlider.  In 2.1 you used to be able to touch anywhere on the slider and the slider would move to that position.  In 2.2 some people complained that they were accidentally changing settings and thus it was removed. So…

Gotcha #3: If you do not add a thumb image in your slider you will not have any hit area to click on in order to adjust the value of the slider.  You could add a transparent thumb icon if you wanted to provide a hit area but not have the graphic, but remember gotcha #2 above, the UISlider will adjust the size of the slider and you will need to account for that.

To solve this problem, I went in and enabled touch support for a UISlider subclass that I created.  I added touch support for the slider being pressed and again for a finger being moved on the slider.  One important thing that I almost missed was to fire the value changed action on the UISlider so that it would tell any registered selectors that the rating value had changed.

I hope this helps some people out there to avoid some problems and if you have any questions please feel free to leave a comment.  I will try to answer the best I can.

Tags: , , , ,