Saturday, November 6, 2010

Tap2GoBack Development has begin!


From humble beginning my ultimate work finally commences! It may be a blank template with no more than an Icon to show for it, but the life-saving app is finally seeing the light of day.

Monday, October 25, 2010

Lothar 1.01 goes live!

While I was in Austria, the iTunes store finally approved my first iPhone application. Hooray! Lothar has gone live and you can try it out here.

Now, even though it has iAd — which I included because I really want to see that Nissan LEAF commercial! — I've never once seen them appear when running the app, so it's pretty much free and without commercials for all who use it!  Of course, I don't know if anyone besides me will be using it, but if you like it, feel free to drop me a comment. :)

Sunday, October 10, 2010

How to add iAds to your iOS app

If you've tried to add an iAd to your iPhone / iPod Touch / iPad and been rejected because the app didn't automatically hide when no advertisements were available, here are the instructions how to make that happen.

Note, if you chose to make your iAd appear programmatically, then Apple will have already sent you some basic hints about how to do this.  But if you used Interface Builder to place / orient your iAd widget like I did, the task is much simpler, as explained in the post by That Don Guy linked to above and the advice from Apple will only serve to confuse (though is good to know for an advanced developer).

But let's say you want to expand a widget (of UIView type) over the space where the iAd would normally be when no iAd is available?  The easiest way I've found to do this is to use Interface Builder to lay out the UIView as if the iAd was there, but make sure the iAd starts hidden by checking the box in the Attributes properties for it.

Then, in your module header file for the parent UIViewController containing these widgets, add a variable to hold the default size of the UIView as designed in Interface Builder:
CGFloat default_view_height;

Once the header file is modified, it's time to update the module.  First, we need to calculate the default_view_height when the view first displays. We can do this in our - (void)viewDidLoad handler:
// Store the UIView height to restore it if the iAd disappears
default_view_height = my_view.frame.size.height;
where my_view is the outlet for the UIView you wish to expand.

Now, we need to expand the UIView into the iAd space by default since the iAd starts hidden; again we do this in the - (void)viewDidLoad slot:
// Since the iAd starts hidden, make the UIView full-sized
my_view.frame = CGRectMake(my_view.frame.origin.x,
my_view.frame.origin.y,
my_view.frame.size.width,
iad_view.frame.origin.y +
iad_view.frame.size.height -
my_view.frame.origin.y);
where iad_view is the outlet for your iAd.

Now you need to implement the 2 ADBannerViewDelegate handlers for when an iAd becomes available and when none are any more.  You should already have these handlers from That Don Guy's instructions; we're just going to add some code to take care of the expansion:
- (void) bannerViewDidLoadAd:(ADBannerView *) banner {
// Shrink web view to allow iAd space
my_view.frame = CGRectMake(my_view.frame.origin.x,
my_view.frame.origin.y,
my_view.frame.size.width,
default_view_height);

iad_view.hidden = NO;
}

- (void) bannerView:(ADBannerView *) banner didFailToReceiveAdWithError:(NSError *) error {
iad_view.hidden = YES;

// Expand web view to fill space
my_view.frame = CGRectMake(my_view.frame.origin.x,
my_view.frame.origin.y,
my_view.frame.size.width,
iad_view.frame.origin.y +
iad_view.frame.size.height -
my_view.frame.origin.y);
}

Compile your iApp and Bob's your uncle!

Tuesday, August 24, 2010

Tip of the Day: How to Zip your App

One thing I have found rather glossed over in the development of iPhone Applications is the format used to upload your app.  Currently, there is an program you can download from iTunes Connect called the Application Loader.  The Application Loader directly connects you to the iTunes Connect site and allows you to upload any App for which you have already created a profile.  So assuming you've created your application profile and just need to upload the binary, you are now faced with a rather mysterious problem.  When you open Application Loader and set up your connection, you are presented with a file dialog to select the binary.  The only problem is that nothing in your development folder is acceptable to this application.  Not any application, be it debug, release or distribution, no library, no file; it's all grayed out.  What's a developer to do?

The answer is quite simple: Zip It.  However, you can't just zip the file.  As far as I know, there is no GUI tool on the Macintosh that can zip application binaries. 

Thanks to aeldron this has become much simpler for you, my fellow developer.  Simply open Finder and navigate to your application's development directory.  From there, you want to find your application, which should be in the directory build/Distribution-iphoneos.  Next, right-click / control-click / two-fingered-click on the file[1] YourAppName.app, replacing YourAppName with the name of your App.  In the pop-up / context menu that appears, select Compress and a corresponding YourAppName.zip should be created.

Now, when you start Application Loader you will see your zip file in black in your build/Distribution-iphoneos directory and you will be able to select it for upload.  Hooray, now the long and nervous wait: will they accept my App?

Or do it via the command line


If you feel you're a hard-core developer who want to get her hands on every aspect of how things work, you can still simply resort to the command line, but here's where things get tricky.  I'll assume you, the reader, know how to execute the Terminal program typically found in /Applications/Utilities/Terminal.app and how to change directory (hint: cd) to the directory containing your project.  I'll therefore assume you're in your project directory.  I'll make one more assumption here: that your binary is located in the folder Distribution-iphoneos; this should be typical if you followed most guides for building your iPhone App and I hope to have a guide to this at a later date.

So, to zip up your binary, type the following commands:
cd build/Distribution-iphoneos
zip -yr ../../YourAppName.zip YourAppName.app
replacing YourAppName with the name of your App.  This puts a file called YourAppName.zip in your project's root folder.  Now, when you start Application Loader you will see your zip file in black and you will be able to select it for upload.  Hooray, now the long and nervous wait: will they accept my App?

One final note for you, my fellow iPhone Application Developer: be very careful to include both the y and r parameters to your zip command line.  r causes zip to include all the files within your application, using recursion to encapsulate everything within.  y on the other hand is much more subtle.  Without y, zip will translate every symbolic link into a copy of the thing to which it points.  Since your application contains symbolic links, this is significant since iTunes Connect needs those to remain links and not be replaced with solid copies.  Thus, the y is necessary for to keep your application in the format expected by iTunes Connect and required by the Application Loader.

See, I told you it wasn't obvious!
-----
[1]Technically, the .app entry is a directory, but appears as a file in Finder; you can see this directory's contents by right-click / control-click / two-fingered-click it and selecting Show Contents from the context menu.

Monday, August 16, 2010

About Lothar

Lothar Collatz was born 6 July 1910 in Amsberg, Westphalia.  During his post-doctoral studies at at the age of 27, Collatz developed what is now known as the Collatz Conjecture.

Simply stated, the Collatz Conjecture is defined in terms of the predicted properties of a rudimentary function.

We define Collatz's function, f, as:

f(n) = \begin{cases} \frac{n}{2} & \text{if $n \equiv 0$ (mod 2)} \\ 3 n + 1 & \text{if $n \equiv 1$ (mod 2)} \end{cases}

for any positive starting integer n, the conjecture states that repeated iterations of this function will always lead to the cycle { 4, 2, 1 }.  In other words, repeatedly applying this function to some starting number will in the long run cause the number
to become smaller and that there are no other cycles in the sequence besides { 4, 2, 1 }.  To this day, no-one has been able to fully prove this conjecture holds true for all natural numbers but clearly it has for every number as yet tested.  Do you think you can find the exception that will prove Lothar wrong?

The inverse function, f-1, is defined as the sequence moving backward from an ending integer through to some initial starting integer that would eventually arrive at the number entered through a series of forward iterations. It is defined as follows:

f^{-1}(n) = \begin{cases} 2 n & \text{if $n \equiv 0, 1, 2, 3, 5$ (mod 6)} \\ \frac{n - 1}{3} & \text{if $n \equiv 4$ (mod 6) \& ``Previous'' pressed} \\ 2 n & \text{if $n \equiv 4$ (mod 6) \& ``Multiply'' pressed} \end{cases}

This application was written by Jeffrey C. Jacobs and is Copyright ©2010 TimeHorse, LLC; source code is available upon request.

Support

To use Lothar, you enter a number into the edit box using the keypad provided and then hit the next to precede through successive values in the Collatz numeric sequence.  To follow the sequence in reverse, activate the reverse switch and click the previous button through successive iterations.  Occasionally, when viewing the previous numeric values in the Collatz sequence, a multiply button will appear.  Where as normally this number could have been arrived at by taking an odd number, multiplying by 3 and adding 1, it's also possible that number was arrived at by dividing some number by 2.  By default, previous always selects the first option; select multiply to select the second.

Clicking on the i will take you to the about screen where you can learn more about the Collatz algorithm and about the man who first described it, Lothar Collatz.  The about page is a built-in web browser with forward, back and reload buttons.  When a page is loading, the reload button becomes as stop button to stop the action.  There is also a home button to take you back to the original about screen.  Note the about page is stored within the application and does not need to use the Internet to retrieve data.  However, clicking links on the about page will load external data to the applications web browser.

If you have any support questions, please ask them here and I shall try to address them as quickly as possible.

iPhone App Info Page, a Tutorial as I learn

This is a tutorial for creating modal information pages for your iPhone apps.  I will assume the reader has basic skill with XCode and Apple's Interface Builder but is basically a novice when it comes to iPhone Development.

  1. Create or open you iPhone App.

  2. Go to the XCode main application window and open your main View Controller, in the Classes folder. It should have a name like YourApplicationNameViewController.h for the header file and .m for the implementation.

  3. In your header (.h) file, add this line within your @interface definition:
    - (IBAction) onInfo:(id) sender;
    Right before the @end is a good place to put it.

  4. In your implementation (.m) file, add the function definition:
    - (IBAction) onInfo:(id) sender
    {
    }
    We will provide the implementation for this shortly.

  5. Now, back to the XCode project window; we're going to create a handler for our Info window.  Control-click the Classes group and select Add file….

  6. From the list of options, under iPhone OS, select Cocoa Touch Class.  Then, from the list of file types on the left, select UIViewController subclass.  Check the With XIB for user interface box to create a corresponding view that we will edit later in the Interface Builder.  Finally, click the Next button in the bottom, right corner.

  7. In the next window, we will change the File Name: to InfoViewController.m and leave the location, project and target untouched.

  8. In your Info header (InfoViewController.h) file, add this line within your @interface definition:
    - (IBAction) onDone:(id) sender;
    Right before the @end is a good place to put them.

  9. In your Info source implementation (InfoViewController.m) file, add the function definitions:
    - (IBAction) onDone:(id) sender
    {
    // Tell the parent window to close this window
    [self.parentViewController dismissModalViewControllerAnimated: YES];
    }

  10. We are now ready to provide an implementation for the onInfo function; return to your YourApplicationNameViewController.m implementation file and provide the following definition:
    - (IBAction) onInfo:(id) sender
    {
    // Create a new Info View
    InfoViewController *info = [[InfoViewController alloc] init];

    // Display the newly created view window
    [self presentModalViewController: info animated: YES];

    // Free the reference to the newly created window so that it can be managed by the OS
    [info release];
    }

  11. We are now ready to create the user interface elements which will control our Info window.  Return to the XCode project; in the Resources folder of you application, double click the file that is your main interface file.  If you are using the Model-View-Controller template, this file should be called YourApplicationNameViewController.xib, for other application types, it may be some other file ending in .xib.  This opens Interface Builder.

  12. From the Library dialog in Interface Builder, select the Round Rect Button control and drag it onto your View — it may not look like it now, but this is going to be your i info button.

  13. You should now see the Button Attributes panel; in this dialog, under Type select Info Light or Info Dark.  Your button now looks like a standard i.

  14. Finally, we must link this new button to our handler; in the View Controller Attributes, select the second tab, with the rightward-pointing arrow; the title suffix of this window will change to Connections.

  15. Pick up the empty circle next to the text Touch Up Inside and drag it on top of the First Responder box within the corresponding .xib window.  From the drop menu, select our onInfo method; that method will now handle the event when the user clicks on the i button.

  16. Return to XCode now, so we can edit the Info Window that this button will invoke.  For some reason, XCode creates your new Info .xib file in the Classes folder with the new source files; it's a good idea to move this file to the root directory of your project with the other .xib files but I will leave that as an exercise for the reader.  In addition to this, you should move the Info .xib file to the Resources folder of your project for consistency.

  17. Once you've found and moved your InfoViewController.xib to the right location, double-click on it to edit it in Interface Builder.  You will see a blank page.

  18. Now, if you want your application to look normal, you probably want to create a standard Done button.  To do this, you first need a Toolbar from the widget Library; drag this to the top of your new view.  Now, select the embedded button labeled Item and under Identifier, select Done from the drop list.

  19. To display our software credits and information, we need a scrollable view.  This can be achieved with the Text View widget; drag one of these onto your view.  In the Text View Attributes rollup, be sure to uncheck the Editable button to keep your credits from being changed by the user accidentally.  Now, for the Text of your view, enter the text you want to appear in your credits screen.  Be mindful of any external links: they can be automatically detected if you check the Links box, as well as addresses and Phone numbers and calendar events.  But if you use these features, when the user clicks on any of the generated links, your application will automatically be exited and the application on the iPhone responsible for handling the request (Safari, Phone, etc.) will be loaded instead.

  20. Now we're going to hook up our controls to the handlers we created earlier.  Starting with the Done button, and under the Bar Button Item Attributes roll-up, select the second tab, with the forward arrow.  There you will see a section called Sent Actions and under that selector.  Across from selector is a circle; select that circle and drag it over to the Info.xib window, dropping it on top of the First Responder container.  A drop list will appear where you can select the handler your wrote, onDone:.

  21. Return to XCode and compile and test; you should now see the info button you just created and when you click on it, up pops your information, about and credits screen.  Now press the Done button to return to your main screen.

Congratulations!  You now have a working information page for your app!

I leave it as an exercise for the reader with respect to loading the text of the Info Page into your about UITextView widget dynamically and how to implement a full web-browser for your credits with the help of a UIWebView widget.  Look for the answers in a future tutorial.

Tuesday, August 3, 2010

Tip of the day: iPod Library Access Programming Guide

Get it here!  Having looked through this framework, I think I will be able to bring you the life-saving Tap 2 Go Back application sooner that I'd hoped!  It may, in fact, be only a few lines of code to set up the application to essentially interpret any click on the screen as a message to go back 7 seconds, or to the last 7 seconds of the previous track if at the beginning.  The driver-safe, work-out safe, hands-free solution to listening to your audio books and podcasts on the device for which they were intended!

Okay, that's enough hyperbole!

Monday, August 2, 2010

Sunday, August 1, 2010

Letter to Apple Developer's Documents: More How less What

Apple,

Your document design guidelines are really nice.  They tell me exactly what my application should look like.  Wonderful!  So, one simple question, then, if that's alright with you: how do I get it to do that!?

Can't you provide some sample code, some screen captures from XCode, whatever.  How do I set the Launch Image for my application.  Yes, I know what a Launch Image is.  It sound's really cool.  I want one; I'm convinced!  So how do I add one to my application??.

For that matter, how do I add the little "i" info button to my application?  Everyone is using this but I don't know how they're doing it!  You'd think if this was part of the uniform interface standard you could again at least provide some sample code?  Please??

Why must this be so difficult — I haven't even started delving into the Core Audio API!

Wednesday, July 28, 2010

More rants about the iPod Nano

Just a quick post here to reiterate why Tap to Go Back is so important to me.  When I was getting ready to go home from work today, I decided to boot up my Garmin GPS to find me the best way around rush-hour traffic.  Of course, when you most need this kind of cellular routing, this particular unit has a nasty habit of acting as if it has no traffic software what-so-ever.  So try as I might, there's no way to force it to load data and I get in the car and head home in the typical direction.

As I approach the Capital Beltway I495 / I95 / I395 "Mixing Bowl" Springfield Interchange, the traffic data finally comes in, only 30 minutes too late.  So I take a hard right to follow its new directions pleasantly listening to the Radiolab Podcast while I head of into new and unexplored traffic.  After 69 minutes constantly following some other car as an occasional snail's pace, I spot a Noodles & Company and decide that since I hadn't eaten since my 5a30 banana I may as well get a bite and let the traffic calm down a little.

So here I am, listening to my podcast, trying to find a parking space when something interesting happens and I miss a bit of podcast dialog.  So I press-and-hold the rewind button for a few seconds and when I let go, I'm at the beginning of the podcast again.  So I've lost my place and as I'm trying to figure out what's happened as I'm trying to park some lady sneaks up behind me and nearly rear-ends me!  Needless to say, I had more than a few choice words — but not for that driver, for Steve Jobs and Apple for designing such a flawed device for playing back spoken word.

In the end, I lost 32 minutes of my life trying to reach the place where I had left off before I was so rudely sent back to be beginning.  Mr. Jobs, my time back please.

I've said it before and I'll say it again: Tap to Go Back is the most important iPhone app to ever be written.  It is life saving, stabilizing, rational, common-sense and for the most insane reason in the universe, it looks like it's up to me to write it!

Tuesday, July 27, 2010

Lothar

Rather than jump right into the Cocoa CoreAudio API, which no doubt will be causing me to pull out my few remaining hairs as I try to figure out what I could so easily do in Python on the PC or AppleScript on the Mac, I decided to first try a trial app as a sort of self-designed tutorial for how to write an iPhone app.

So I bought into the $99 developer's license and started to learn Objective-C. Objective-C isn't a particularly hard language, though the way everything seems to be a message and have only run-time binding is a bit tricky to get right.  But I'm learning.

The App I'm developing is called Lothar.  It is a simple number game that will compute all the numbers in the Collatz sequence — hence the name Lothar for Lothar Collatz and who recently celebrated (posthumously) his 100th birthday.  The algorithm is quite simple: if the number n is odd, then multiply n by 3 and add 1, making it even.  If the number is even, divide it by 2, which may still be even or may become odd.  When this algorithm has been applied to any positive integer it has always turned out that the sequence will end with the repeating subset 1, 4, 2.  By this I mean no-one has yet found a positive number for which this is not true, making this an undisputed theory, though not a fact.

Lothar also performs the reverse algorithm: when the number is odd, it is multiplied by 2, as well as when it is even and not equivalent to 1 modulo 3.  When the number is even and equivalent to 1 modulo 3 (e.g. 4, 10, 16, etc.), this number could have been arrived at in one of 2 ways using the Collatz algorithm: a) it was due to an odd number, so the previous number is (n - 1) ÷ 3 or b) it was due to an even number, so the previous number is n × 2.  This is handled by having a second button, labeled Multiply, appear.  Clicking Multiply performs b) and clicking Previous performs a).

Currently, the application is mostly complete.  There are only 2 concerns I have at the moment.  1) If you reverse the calculation enough, the number becomes so big it becomes negative.  Why this happens is a bit complicated to explain to someone who's never programmed before, but needless to say I need to adjust the application to prevent this from happening by disabling all buttons when the next result would overflow the number.  2) I want to create an Info page to tell the user a bit about me, TimeHorse, Multimedia and about the algorithm; I may even want to put a link to the Lothar Collatz wikipedia page.

Once that's done, I plan to submit it to the Apple Store.  After that, I have some ideas for enhancements, such as providing for negative number entry, allowing the user to enter custom algorithms, and so on.  But for now, I just want to get the application done and submitted and start the grueling work of my true calling: Tap to Go Back.

Tuesday, July 6, 2010

What is Tap to Go Back

I'm creating this blog to document and encourage me to solve a problem that is currently the bane of my existence (well, one of many banes, but we'll leave those issues for another blog).

First of, let's lay some ground rules. I don't listen to music. At least, I don't when I drive, exercise, clean house or do any other form of mindless activity. Music is fine for thoughtful activities for me, such as programming because then the music becomes the background and the ideas I'm weaving become the foreground. But when I'm doing something that does not require much thought, I want to use that time to expand my mind, be it by audio book, audio dramatizations or podcast.

That said, no activity is completely mindless. If I need to hit a busy intersection or change machines or someone wants to talk to me, I need to be able to quickly go back and have my player repeat the last 5 or so seconds of dialog I just missed because something more important came up.

In other words, I need a Skip Back function for my portable content players. By this, I mean iPod, iPhone, Droid or what have you. As it is, I don't have a Droid and since Droids can't, as far as I know, play m4a (aac) files, I'm pretty much limited to the i for the time being. And since most of the iPods aren't opened source or allow app development, the iPhone / iPod Touch is it, it seems.

What's that you say? The iPod can be rewound? Yes, it can, but try hitting an iPod Nano rewind button squarely while driving. I mean squarely, because if you miss and hit the center and rewind button at the same time, it will call up the menu and restart the current track no matter how long you hold down the rewind button. And in an hour-long podcast, going back to the beginning when you only wanted to go back 5 seconds is a nightmare upon nightmare!

That's, of course, in addition to the problem faced by even the iPod Classic, with it's man-finger sized buttons. Don't hold that rewind button long enough or get jumped by a distraction or bump on the treadmill or in the road and you're doomed to repeat again and again! And on the iPhone / iPod Touch, your expected to hit this small, non-tactile circle to set you back 30 seconds while keeping your eyes on the road and with at least 1 hand on the equipment to keep from falling. Yikes! It's just not practical! And don't get me started on the obscene tap-tap-hold interface of the new iPod Shuffle!

If I could get the older iPod Shuffle Generation 2 again, I'd be more sanguine. The buttons were large enough, since the rewind was beveled and thus quite nice for playing audio books when the shuffle was turned off. But my little green guy never remembers what played so I'm still doomed to repeat because the computer keeps adding it back, thinking I didn't hear it; or worse, has a tendency to mark things I never heard as listened to and then I never hear them, ever!

This is just not right! Apple needs to get its act together, but since that monolithic behemoth of a company could care less about the little man, it's up to me. And that is my task; this is my goal.

Watch this space.