Thursday, October 2, 2014

Maybe I'm asking the impossible

But I just would like a way for my iOS app to figure out the current playback position and then do a calculation such that if one skips back before to a point before the beginning of the current track, the app will go to the end of the previous track as if they were continuous. I posted the query on StackOverflow but so far no reply leading me to believe I've asked the impossible. How frustrating.

iOS: It there a way to get and set the current playback position?

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.