Adding Array Subscripting To Your Classes in Objective-C

Xcode 4.4 added some great new literals syntax for collection classes and numbers, so now you can write NSArray *array = [@”one”, @”two”, @”three”]; And you can access those elements with array-style subscripting like this NSString *s = array[1];

On it own, that’s great, but there’s more under the surface here. When you write array[1], the compiler translates that into a method call named objectAtIndexSubscript:, which is implemented by NSArray. The cool part is that you can implement this method in your own classes, and then use subscripting on instances of your classes. You can also implement the sister method: setObject:atIndexedSubscript: to set values.

The code below is a simple example of how you could use this:

// Header

@interface ItemCollection : NSObject

@property (strong) NSMutableArray *list;

// Suport for Array-style subscripting. Ex. items[4] = @”hello”;

– (void)setObject:(id)anObject atIndexedSubscript:(NSUInteger)idx;

– (id)objectAtIndexedSubscript:(NSUInteger)idx;

@end

// Implementation

@implementation ItemCollection

– (void)setObject:(id)anObject atIndexedSubscript:(NSUInteger)idx {

self.list[idx] = anObject;

}

– (id)objectAtIndexedSubscript:(NSUInteger)idx {

return self.list[idx];

}

@end

// Using the class

ItemCollection *items = [ItemCollection new];

items[1] = @”boo”;

This is a contrived example, but with some imagination, you could find some cool uses for this to make your code more concise. Not only is this available for arrays, but you can use the key-value methods used by NSDictionary as well – objectForKeyedSubscript: and setObjectForKeyedSubscript:

You can read more about this here: http://clang.llvm.org/docs/ObjectiveCLiterals.html


How To Make Great App Videos

With over 700,000 apps in the Apple App Store alone, the mobile app market has become incredibly competitive. So the success of your app in this environment has as much to do with marketing as it does with building a great app. One of the best tools you can use to market your app is a great app video. For most apps, a few screenshots don’t really convey just how cool your app is; not the way a video can.

The problem is, if you’ve ever attempted to make an app video, you’ll discover it can quickly turn into something sad. You need someone with real camera and editing skills to produce a video of your app running on an actual device. And taking a screen recording looks like, well, like you took a screen recording. So today I’m going to summarize a process that I’ve come up with to make slick, polished app videos that you won’t be embarrassed to post on your app web site. I’ll talk about some tools to record and edit your videos and then discuss exporting and publishing your videos.

Here is an example of a video I made to demonstrate the basics of the Coachable Soccer iPad app:

Screen Recording

To record the screen without making it look like we recorded the screen, we need to accomplish a few goals:

  1. We need to record the screen (obviously)
  2. We want to see the device hardware in the video
  3. We don’t want to see the mouse cursor. Rather we want to see some “touch” pointer instead.
  4. We don’t want our desktop in the video. A solid background would be nice.

Recording the screen would be easy if we used Quicktime Player 10. It allows you to record a portion of the screen and makes nice videos, but sadly your cursor will always appear in the videos. If Apple added that one feature, our lives would be so much easier. Instead, we turn to third party screen recording software. There are several out there.

Screenflick

 I settled on Screenflick [http://www.araelium.com/screenflick] which sells for $30. You can try it for free first, and live with a giant watermark on your videos until you decide to commit.Screenflick is solid screen recording software with a simple interface and some cool features. Foremost is the ability to remove the cursor from your videos. It also has the ability to overlay an image during all or a portion of the video and some keyboard stroke display options for your video output.

The next problem to solve is displaying the device hardware in our video. The iOS Simulator only displays decent hardware chrome for the old iPhone, which might be okay for you, but you’re not getting the best resolution possible and you’re out of luck if you want to demo an iPad app. The Retina Display iPhone hardware option does have a bezel but it looks nothing like the real device.

SimFinger

Here is SimFinger running with a retina display iPhone simulator. It’s the right idea, but doesn’t fit.

One way to solve this problem is with an application called SimFinger. This is an open source application living on github that has been neglected for the past couple years. It’s a cool concept that could use some spiffing up and updating. To get it, you’ll have to download the source code from the project on github: https://github.com/atebits/SimFinger There are a bunch of projects bundled in there but the one you want is called FakeFinger. The idea is you run the simulator, then you run FakeFinger and it displays a device overlay (with a hole in the middle) on your screen directly over the simulator window. It also provides a slick white touch pointer for that extra jazz. The problem with it is that its images and hard-coded screen resolutions are outdated and don’t work with all the new iPhone and iPad simulator sizes. If you’re handy with Objective-C (and you should be if you wrote such a great app) you can hack the project code yourself and figure out what resolutions are appropriate for your task. You might have to do some image hacking too. I did to get an iPad overlay that was the right size for my screen.

You also have the option to turn the touch pointer on or off. You’ll probably want it on, unless you’re using another application to provide a custom pointer.

PinPoint

Another app I came across in my research was PinPoint [http://www.lagentesoft.com/pinpoint]. Again, there are several apps out there to customize your mouse pointer, but this is the one I settled on. It has a bunch of great built-in customizable pointers, as well as the option to import your own designs into the application. It also has a nice key stroke display option which would be great for doing desktop application demo videos. This app is only $5 from the App Store.

I used PinPoint in some of my videos because I wanted a non-white touch pointer that would appear more clearly on a light-colored app background.

Create the Screen Recording

Once you have SimFinger running the way you want it to, and you’ve sorted out the touch pointer, you are ready to record a screen video with Screenflick.

The process is simple. Click ‘Start Recording’ and choose the area you want to record. I suggest choosing a sane aspect ratio like 4:3 to make your life easier. If it’s going to stretch beyond the limits of the SimFinger overlay, just make your desktop background white. When you’re done, press Cmd-Shft-2 to stop the recording.

In Screenflick’s Movie tab, you can add options to your video, like removing the cursor and adding a image like an icon to the video.

The best option for video export is to Export to Quicktime H.264. This is what seems to work best with Apple applications like iMovie.

Movie Editing with iMovie

Now you have a raw screen recording of your app. Don’t stop there. Get the latest version of iMovie for $15 and give your video a professional touch. iMovie is powerful, but it’s still a consumer grade product. It’s meant for making quaint home videos of your European vacation, so it’s lacking what seem like obvious features, like support for aspect ratios beyond 4:3 and 16:9. This makes it tough to use iMovie to edit anything non-standard that you want to embed on your web site. If that’s what you want, you need to shell out $300 for Final Cut Pro…and then learn how to use it.

In iMovie, we import raw videos and sort them into “Events”. Try creating an event for each app. Then you create a new project and drag-n-drop chunks of video from your events. Be careful when importing videos into iMovie when it offers to optimize your videos. My first attempt ended with a video at 1/4 the original resolution once I was done exporting it. Just import the raw full resolution video.

I won’t go into detail about how to use iMovie. It’s relatively intuitive to use. You can slice your video project into chunks. You can drag in various effects like text titles to precede a video chunk, or to overlay a video chunk. You can also drag your own images into these text titles. It doesn’t take long to get some slick looking effects going.

iMovie Interface

You can also add music to your video project. You can trim the music chunks, adjust the volume, change the fading of the clip, and many other cool features. You can import directly from your iTunes collection or from Garageband. To be clear, be wary of using copyrighted music in your app videos, especially if you’re planning to post them on YouTube. I managed to use Garageband loops to create the background music for my videos. If you’re more talented, you can use Garageband to create more sophisticated compositions. Royalty free music is another option; an option that isn’t always free…just royalty-free. There’s a difference.

Exporting Video

When your masterpiece is complete, it’s time to export it to a video format we can use in YouTube or an HTML 5 web site. If you want to upload to YouTube, choose Export Using Quicktime from the iMovie Share Menu. This should get you the best video to upload. You can find full specs and explanations here: http://support.google.com/youtube/bin/answer.py?hl=en&answer=1297408

For video to embed in your site, I prefer Share Movie -> Export Movie and export to the biggest .m4v mp4 you can.

Converting Video

Miro Video Converter – It’s so easy to use. And it’s free!

If you’re posting your video directly on your site, you’ll need more than one video format. Sadly browser makers can’t agree on a video format. Firefox doesn’t support H.264, but only webm or ogg theora. I think H.264 is supported by all the other major browsers, even IE 9.

The tool to convert your video is the free Miro Video Converter. [http://mirovideoconverter.com] This program is a jewel! I wish all apps were this easy to use. Simply drag your video file into the Miro window, choose an export format and click “Convert”.

HTML 5 Video

In theory, HTML 5 makes video a breeze. No need for flash. Simple tags. Fully featured video player embedded in the browser. But of course it’s not.

We already learned that the browsers support different formats so you’re going to need two versions of each video. Once we have that, the video tag is pretty simple:

<video controls width=”405″ height=”540″>
<source src=”./video/MyVideo.webm” type=’video/webm”>
<source src=”./video/MyVideo.m4v” type=”video/mp4″>
<img src=”./images/MyAppScreenshot.png”>
</video>
Make sure your html document has the magic HTML 5 doc type tag: <!DOCTYPE HTML> at the top of the page. Without this, some browsers (IE9, *cough, cough*) won’t realize how to use the video tag. The final gotcha is to put a file called .htaccess in the folder with your videos. It should look something like this:

AddType video/ogg .ogv
AddType video/mp4 .mp4
AddType video/m4v .m4v
AddType video/webm .webm
AddType video/x-m4v .m4v

This tells the browser that the file format ending in mp4 is of the mime type video/mp4, and so on… This is the kind of stuff that wrecks the fun of web development for me, but that’s another article…

Conclusion

And that’s it. There are a lot of steps involved in making a great app video, which is why I wanted to put it all in one place. I spent a lot of time on Stack Overflow and various support forums over the course of a couple days trying to get this all figured out. Hopefully an article like this will make it easier for others…and for me when I forget it all ten months from now.


Combining Blocks, Properties and Animation in Objective-C

Blocks are a recent addition to iOS and Mac development. It’s a C-level feature, and is available in the XCode tools in Snow Leopard and for iOS 4.0 and later. The support in UIKit and Foundation libraries is still a work in progress, but a lot of important Cocoa classes already offer support for this language feature.

I’m not going to explain all the details of blocks. The Apple documentation does a fair job of that already. Good resources are Block Programming Topics and A Short Practical Guide To Blocks. Instead of rehashing that stuff, I’d like to explore some ideas of how to use blocks in our Objective-C programs. Learning any new language feature is like getting a new hammer for Christmas: You start looking for nails. I’m still early in my search for nails to hit with this hammer, but the first thing I wanted to try was inspired by my very limited knowledge of the javascript language.

Javascript, and other languages, have the concept of closures, which is a powerful but often poorly understood concept, but it forms the basis for a lot of the really cool stuff that’s recently emerged in web development, like jQuery. Blocks are essentially closures for Objective-C. And I wondered if you could therefore start assigning anonymous bits of code (and the variables in their scope) to object properties in Objective-C. It turns out you can, and it’s awesome!

I will step through some code examples to show you what I mean. And I’ve posted the sample project that all this code comes from here: https://github.com/silromen/ObjectiveScript

This sample project, called ObjectiveScript, is pretty simple. There’s an image we can animate by tapping it. We can switch how the image animates by tapping one of three buttons: Rotate, Scale and Transform. Once a button is tapped, we tap the image and it performs the chosen type of animation.

There are two main classes: the ViewController and the View which contains the image we want to animate.

Let’s start with the animateable view, here called SpecialView:


//  SpecialView.h

#import
@interface SpecialView : UIView {
	void (^animation)(void);
}

@property (nonatomic, copy) void (^animation)(void);
@end

Look at that property declaration! It’s saying that this object has a property called animation that we can assign an arbitrary block of code to, which returns nothing and takes no arguments. This is different than declaring a method, because the code in a method has to be defined at compile time. With a block, we can assign any code we want to that property at run time.

Now let’s look at the source code for our SpecialView.


//  SpecialView.m

#import "SpecialView.h"

@implementation SpecialView
@synthesize animation;

- (void)dealloc {
    [super dealloc];
	[animation release];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
	[UIView animateWithDuration:0.85
						  delay:0
						options:UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse
					 animations:self.animation
					 completion:^(BOOL finished){
						 self.transform = CGAffineTransformIdentity;
					 }];
}
@end

There’s not a lot of code, but there’s a lot going on here. We’re synthesizing and releasing our property – that’s normal. We’re overriding touchesEnded and defining an animation we want to occur whenever a touch event ends on this view. Now, in the old days (last year), without going deep into Core Animation Layers, you animated a view by defining some changes to the view you wanted animated and bookending those instructions with [UIView beginAnimations: context:] and [UIView commitAnimations], and if it pleased you, you could specify a selector to run when the animation completed. But since iOS 4.0, there’s a block-friendly way of doing exactly the same thing, and that’s what is happening in this code sample. We’re calling the class method animateWithDuration:delay:options:animations:completion:. The animations and completion parameters are accepting blocks of anonymous code. What’s really special in this example, is we’re passing the contents of our view’s animation property as the block to execute for the animation. The completion code is always going to be the same, which is to undo any transformation that the animation has performed on the view by setting the UIView transform property to the identity matrix. But the animation itself could be any chunk of code we assign that animation property to.

So let’s see how the ViewController puts that cool feature into use.


//  ObjectiveScriptViewController.h

#import
#import "SpecialView.h"

@interface ObjectiveScriptViewController : UIViewController {
	IBOutlet SpecialView *specialView;
	IBOutlet UIButton *rotateButton;
	IBOutlet UIButton *translateButton;
	IBOutlet UIButton *scaleButton;
}

- (IBAction)onRotate:(id)sender;
- (IBAction)onTranslate:(id)sender;
- (IBAction)onScale:(id)sender;
- (void)setSelected:(UIButton*)sender;
@end

In the header, we have our outlets for the special view and the buttons. We have our handlers which are called in response to the buttons being touched, and we have a helper method that will be used to make the three buttons behave like radio buttons, so only one is selected at a time.

 
//  ObjectiveScriptViewController.m

#import "ObjectiveScriptViewController.h"

@implementation ObjectiveScriptViewController

- (void)dealloc {
	[specialView release];
        [super dealloc];
}

- (IBAction)onRotate:(id)sender {
	specialView.animation = ^{
		 [UIView setAnimationRepeatCount:1.0];
		specialView.transform = CGAffineTransformRotate(CGAffineTransformIdentity, 135.0);
	};
	[self setSelected:(UIButton*)sender];
}

- (IBAction)onTranslate:(id)sender {
	specialView.animation = ^{
		 [UIView setAnimationRepeatCount:1.0];
		specialView.transform = CGAffineTransformMakeTranslation(-175, -175);
	};
	[self setSelected:(UIButton*)sender];
}

- (IBAction)onScale:(id)sender {
	specialView.animation = ^{
		 [UIView setAnimationRepeatCount:1.0];
		specialView.transform = CGAffineTransformMakeScale(0.1, 0.1);
	};
	[self setSelected:(UIButton*)sender];
}

- (void)setSelected:(UIButton*)sender {
	rotateButton.selected = ([sender isEqual:rotateButton]) ? YES : NO;
	translateButton.selected = ([sender isEqual:translateButton]) ? YES : NO;
	scaleButton.selected = ([sender isEqual:scaleButton]) ? YES : NO;
}
@end

Notice how each button’s handler method assigns a chunk of animation code to the SpecialView’s animation property. Tapping these buttons doesn’t execute the animation, but they tell the view which animations to perform by feeding it the code to execute.

The combination of blocks, properties and core animation is powerful, and this example is just scratching the surface. This gives developers another way to conceptualize and organize their code, and having more options is always a good thing.


Mixing PopoverControllers with ModalViewControllers

When building an app on the iPad, sometimes you need to display a Popover, and tapping a button on that Popover will launch a Modal View. When you’re done with the Modal View, it flies away (gotta love those animations), and you’re back to the Popover.

This doesn’t seem like a stretch, but if you’re not careful in how you do it, iOS has some nasty surprises in store for you.

So here’s what you’re trying to accomplish:

Let’s take a first attempt at the code for this:

@implementation ModalPlusPopoverViewController
...
// When the Go Button is pressed, we create a view controller, embed it in a popover controller and present it.
- (IBAction)goPressed:(id)sender {
	MyViewController *theViewController = [[[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil] autorelease];
	UIPopoverController *popoverController = [[UIPopoverController alloc] initWithContentViewController:theViewController];
	[popoverController setPopoverContentSize:CGSizeMake(400, 400) animated:NO];
	[popoverController presentPopoverFromBarButtonItem:(UIBarButtonItem *)sender
						     permittedArrowDirections:UIPopoverArrowDirectionUp
									       animated:YES];

}
@end
@implementation MyViewController
...
// Inside the popover, when the "Launch Modal" button is pressed, we create our modal view controller and present it
- (IBAction)launchModal:(id)sender {
	MyModalViewController *theModalViewController = [[[MyModalViewController alloc] initWithNibName:@"MyModalViewController" bundle:nil] autorelease];
	theModalViewController.modalPresentationStyle = UIModalPresentationFormSheet;
	[self presentModalViewController:theModalViewController animated:YES];
}
@end
@implementation MyModalViewController
...
// To dismiss the modal, the user taps the Dismiss button, and we dismiss ourselves
- (IBAction)onDismiss:(id)sender {
	[self.parentViewController dismissModalViewControllerAnimated:YES];
}
@end

With this code, everything seems to work well at first glance. When you tap Launch Modal, the modal view slides up from the bottom, and when you tap Dismiss, it slides down again.

But now rotate the iPad and try again. This time, the Modal view slides up from the bottom, but when you dismiss it, it flies out to the left!

And it gets worse. If your modal view happens to be a MFMailComposeViewController, which is a handy class to make it easy for users to send email directly from your app, when you try to dismiss it, it actually causes your app to rotate, even though the iPad is still in landscape orientation.

So what’s going on here?

When you launch and dismiss a modal view from a popover, iOS is doing some strange things under the hood. If you put a breakpoint on shouldAutoRotateToInterfaceOrientation in your popover view controller, you’ll find it gets called when you launch and dismiss the modal. If you examine the call stack you’ll see this call:
[UIViewController _preferredInterfaceOrientationGivenCurrentOrientation:]
So there’s some calculation going on under the hood that’s making an orientation decision. When your modal view is MFMailComposeViewController and you dismiss it, you actually get the wrong orientation passed to shouldAutoRotateToInterfaceOrientation: you get UIInterfaceOrientationPortrait when what you’re expecting is UIInterfaceOrientationLandscapeRight. And this is why your iPad display rotates. And I suspect some similar behaviour is causing the modal view to slide out in the wrong direction.

So how do we fix this?

It turns out our mistake is launching the modal view from the popover. It’s this call from the MyViewController class:
[self presentModalViewController:theModalViewController animated:YES];
Here, self refers to the MyViewController class, which is embedded in a Popover. What we need to do is launch the modal view from the underlying view controller, the one that launched the popover view. In our example, that’s ModalPlusPopoverViewController. The problem is the view controller in the popover has no reference to the underlying controller, so we need to add code for that. Our fixed code looks like this:

@implementation ModalPlusPopoverViewController
...
- (IBAction)goPressed:(id)sender {
	MyViewController *theViewController = [[[MyViewController alloc] initWithNibName:@"MyViewController" bundle:nil] autorelease];
       // We now tell the view controller we're embedding in the popover that it should launch modal views from this view controller
	theViewController.baseViewController = self;
	UIPopoverController *popoverController = [[UIPopoverController alloc] initWithContentViewController:theViewController];
	[popoverController setPopoverContentSize:CGSizeMake(400, 400) animated:NO];
	[popoverController presentPopoverFromBarButtonItem:(UIBarButtonItem *)sender
							  permittedArrowDirections:UIPopoverArrowDirectionUp
											  animated:YES];

}
@end
@implementation MyViewController
@synthesize baseViewController;
...
- (IBAction)launchModal:(id)sender {
	MyModalViewController *theModalViewController = [[[MyModalViewController alloc] initWithNibName:@"MyModalViewController" bundle:nil] autorelease];
	theModalViewController.modalPresentationStyle = UIModalPresentationFormSheet;
	[baseViewController presentModalViewController:theModalViewController animated:YES];
}
@end

I’ve omitted the header file code here, but it should be clear what the header files contain based on the source. Now our modal view behaves as expected when we dismiss it. And if we’re presenting a MFMailComposeViewController, it doesn’t auto-rotate the app behind our backs.

The moral of this story is to be careful which objects you launch your modal views from, especially when you’re launching them from Popovers.


Anchor’s Aweigh – For TransitWay

January 20, 2010. The day I finished the first application of my independent software development career. Shipping code doesn’t come along very often – a few times per year at most, so when it happens it’s a big deal. And because of my extended sabbatical, the last time I shipped software was in 2006 – a lifetime ago in the internet age. That was was in the year -1 B.iP. (Before iPhone).

Fast forward to year 3 A.iP. and today I submitted my first app, TransitWay, to the App Store. Everything about this project was engineered to be small, simple and relatively quick, so I could experience the entire software development cycle in a short timeframe (less than 3 months). The app is small. The feature set is small. The market is small. The development cost (in time and money) is small.

My previous development experience was completed within the comfortable confines of a well organized, successful company with full-fledged software, QA, and marketing departments. There was always somebody within 100 metres who knew more than I did about some topic critical to the success of our product, development-related or not. When you start developing software on your own, you get what you ask for: you are on your own. You have to wear many hats, sometimes at the same time. And in order to ever hope to make money, you need to be focused on shipping software. That means knowing your strengths and weaknesses, and choosing a project small enough to complete in a reasonable amount of time, and that supports your enterprise in its current state. The current state of my enterprise is that I’m alone, I’m slightly nervous about what I’m capable of doing with just my ideas, my laptop and my internet connection. So I chose to build a piece of software that I knew there was a need for (because I needed it), and that seemed ridiculously simple, too simple to be a proper project. That turned out to be a fantastic decision. And that ridiculously simple project? It took me nearly 3 months of part-time development time to complete and polish, certainly longer than I had planned, but still a quick turnaround for shippable software.

While I physically work alone, with nothing more than Google and Stack Overflow for co-workers (oh, and the Hannibal Lector action figure on my desk), I have made a conscious effort to grow my professional network. So far, I have joined three local groups in Ottawa: a local Mac User Group, the local chapter of CocoaHeads and its splinter NSCoder group. These groups are critical to my success, because as much as I would love to do everything myself, I can’t, and I have so much to learn from these people. I’ve already found two graphic designers – one who did the TransitWay logo for me, and learned countless life-saving tips from the people I’ve met through my network. These groups are also a potential starting point for drumming up word-of-mouth advertising for my projects.

As I wait for Apple Corp. to pass judgement on my app, I’m taking a breather to reflect on my progress, and to contemplate my future. If my submission is rejected, I’ll be stuck working on TransitWay for a little while longer, but beyond that, I have at least three potential projects on my plate. One is an iPhone game. One is TransitWay 2.0. One is to complete the recipe and meal planning project I started over a year ago, with both desktop and iPhone components. Which ever project I choose, it will certainly involve a whole whack of new learning, and hopefully I can build on the experience I’ve gained from completing the TransitWay iPhone app.