iOS 5 By Tutorials ebook

iOS Apprentice Tutorial 4 Available

I’m happy to announce that the latest ebook from my popular iOS Apprentice series is now available. :-)

The StoreSearch app

In this tutorial you’ll build StoreSearch, an app that lets you search the iTunes store for songs, movies, books and software. You’ll learn about making your mobile apps talk to web services, iPad programming, internationalization… and lots more!

You can get the iOS Apprentice at the Ray Wenderlich store.

 

Freelance iPhone Developer, One Year Later

A year or so ago I wrote a blog post about starting out as a freelance iOS developer. A lot has changed since then. I have no shortage of work and I was able to recently bump up my hourly rate to €150. Because of this, my fiancee and I can afford to take a three-month vacation in Australia soon and I don’t intend to do any work while we’re over there. Of course, I worked hard to make this possible.

If you pay peanuts, you get monkeys

Every day I get inquiries from potential clients, much more work than I could possibly handle. Some of these inquiries are quite unrealistic, but the 150 Euro per hour price tag is quite effective in scaring off the dreamers with a hundred bucks and an idea. (It’s also basic economics: If you can’t keep up with the demand, raise your prices.)

My hourly rate may seem high but one thing I learned over the past year is that I’m a really good developer and that I’m worth it. Asking for big money obviously drives away a lot of potential clients, but the clients that I do get are serious about what they want, their projects are interesting, and they understand what it takes to make a quality product.

As any creative professional can tell you: “The more you pay me, the more you can expect of me, and the harder I will work to make the end result really wonderful.”

Inspired by this excellent rant, I also decided to take on only the really hard projects, the ones that are too hard for other developers. Simple apps are boring — I need challenges that allow me to make the most out of my skills!

How to find work

I received an email today from a fellow freelance developer who found himself in the same spot I was in a year ago:

“I was wondering if you had any more luck finding work via internet resources since your post was written? I figured I’d look around at a couple of the big freelancing sites and see what I can find, but I think it’d be so much better if it was more personal.”

There are two things I did that made all the difference. First off, I started blogging. There’s always a need for good information about any topic in your field, so if you write quality posts you’ll build up a name for yourself and people will come to regard you as an expert.

With a blog full of quality material, you’re no longer some anonymous developer but someone who has already demonstrated his skills. It makes it easier for clients to trust that you can actually deliver.

Putting some of your own code on Github is another way to pull that off. I have created some open source components that people find useful, and that gets my name out there too.

The biggest thing I did, however, was to write for www.raywenderlich.com. That is a popular site with tons of great tutorials and my contributions seem to be appreciated. I also wrote a 750-page ebook called The iOS Apprentice that is sold through Ray’s site, and contributed to the ebook iOS 5 By Tutorials.

A lot of this is hard, unpaid work, but it pays itself back in building up your reputation. I’m probably not as well known in iOS circles as Matt Gemmell or Marco Arment, but I’m working on it. ;-)

Not what you know, but who you know

The second thing is to get in touch with other developers. Networking is a great way to get referrals for jobs. Many developers have too much on their plate so they’d be happy to pass on work to other developers they know and trust. Some will also subcontract out certain parts of their projects.

There are many ways to network. You can get in touch with other developers that are local to you through groups such as CocoaHeads and meetings such as NSCoder Night. If no such group exists in your area, you might consider setting one up yourself.

You don’t have to restrict yourself to just meeting iOS developers, of course. Mobile developers, web developers, designers, start-up founders, these are all useful people to get to know.

Face-to-face networking is probably best, but on the internet there are plenty of places to get in touch with other developers as well: forums, blogs, IRC, Facebook, LinkedIn, you name it. Hanging out with your peers has never been easier…

Transparent JPEG Images

When you distribute images with your app you usually pick the PNG or JPEG format. The advantage of JPEG is that it often compresses better — especially for photos — but unlike PNG it unfortunately does not support transparency.

The transparency in a PNG file comes from the so-called “alpha channel”. For every pixel not only red, green and blue values are stored but also an “alpha” value that determines how transparent that pixel is. A value of 255 means this pixel is fully opaque, 0 is fully transparent, and anything in between will mix the pixel’s RGB values with the underlying color.

This is probably an old trick, but by saving a JPEG image not as one but as two image files you can still have transparent images. The first image is the regular JPEG with as much compression as you can get away with, the second image is the alpha channel. This is a grayscale image with black representing fully transparent, white fully opaque, and gray everything in between.

 

Source image and its alpha channel
We can combine these two images at runtime to make the image transparent again. Because of the JPEG compression we lose a little bit of clarity but if you tweak the compression settings you can usually get away with it.

I wrote a simple category on UIImage that lets you do this.

Preparing your images

1) Export your image from Photoshop as a PNG with transparency.

2) Export the image again as a JPEG, using suitable compression settings. The background should have a solid color, typically white or black but any color will do.

3) Save the alpha channel to a separate JPEG or PNG image. I couldn’t find an easy way to do this from Photoshop, but the ImageMagick tool can do it without problems.

If you have ImageMagick installed, open a Terminal and go to the folder that contains the exported PNG image. Then type:

convert -alpha Extract -type optimize -strip -quality 60 +dither \
    Source.png Alpha.jpg

This extracts the alpha channel from the PNG image and saves it as a JPEG file. You can tweak the level of compression with the -quality parameter. If you specify “Alpha.png” instead of “Alpha.jpg”, ImageMagick saves the alpha channel as a grayscale PNG-8 file. You should use whichever one makes the smallest file size.

Combining the images

1) Add the two JPEG images (the non-transparent source image and the alpha channel) to the app.

2) At some point, call the mh_combineWithAlphaImage:backgroundColor: method to combine these two images into a new, transparent, image.

3) Depending on your app you may want to do this only once and then store the transparent image as a PNG in your app’s Caches folder.

That’s it, quite easy.

Some notes

The alpha image does not have to be a JPEG, it can also be a PNG file. If it is a JPEG then it can have different quality/compression settings from the main image.

The current implementation works well but is not as fast as it could be. It also uses more memory than is strictly necessary. I might rewrite this at some point to use the Accelerate framework or Core Image.

Not all images compress better as JPEG. You should use JPEG only where it makes sense.

Check out the source code at Github.

Bird image by Sias van Schalkwyk

 

MHTabBarController – A custom tab bar for iOS 5 using the new container APIs

Creating your own container view controllers, i.e. view controllers that can contain other view controllers, used to be a pain but now iOS 5 makes it a lot easier.

Especially for iPad apps that is great, because all of that screen space means you probably want to divide it up amongst more than one view controller.

Today I was messing around with these new container APIs and built my own tab bar controller. It works just like a regular UITabBarController, except the tabs look quite different and the pages slide in and out of the screen with a nice animation.

Screenshot of MHTabBarController in the demo app
If you want to learn more about how to do this, then check out the source code or get the iOS 5 by Tutorials ebook. It has a full chapter on these new view controller containment APIs, plus twenty or so other chapters on more iOS 5 goodness!

Making UIBarButtonItems in Photoshop

Recently I was working on an app that required brightly tinted tool bars and navigation bars:

A UIToolBar with a light blue tint color

As you can see, the light blue color makes the bar button hard to see and its label hard to read. Changing the background color of the button is really easy on iOS 5 because its UIBarButtonItem also has a .tintColor property. But if you still need to support iOS 4 then you’re out of luck.

In that case, the only solution is to put a UIButton inside the UIBarButtonItem and give it a background image that looks like a regular bar button. It’s a roundabout way of doing things but it works.

Previously, I would draw these bar button-lookalike images myself in Photoshop. By setting the appropriate layer styles on a rounded rectangle vector object you can make a decent approximation of what a real bar button item looks like.

This time, however, I wanted to take advantage of the actual images that UIKit itself uses to compose the UIBarButtonItem when you change the tintColor of the underlying toolbar or navigation bar.

To pull this off, you can download UIKit Artwork Extractor. Compile the app and run it on the Simulator (or on your device). It will extract all the images that are built into the various iPhone and iPad frameworks and save them to a folder on your computer.

After you have extracted the images, go into the “Shared” subfolder and look for:

  • UITintedButtonHighlight.png
  • UITintedButtonMask.png
  • UITintedButtonShadow.png

You can combine these three images with a fill color to produce a tinted UIBarButtonItem background image, like this:

How to add the different images to produce the final bar button image

The actual layers pane should look like this:

The Layers pane in Photoshop

The “Fill color” layer is simply a rectangle filled with the tint color that you want the button to have. As you can see, both the fill layer and the “shadow” layer are clipped against the red “mask” layer. If you don’t do that, the button won’t have a transparent background in the corners.

To export the image, merge all the visible layers (but not the background!) and save the image as PNG. This gives you a 11×30 pixels stretchable image.

You can use the following category to create the fake bar button items in your code. It requires that the image named “BarButton.png” is added to your project.

@implementation UIBarButtonItem (FakeButtons)
 
- (id)initWithTitle:(NSString *)title width:(CGFloat)width target:(id)target action:(SEL)action
{
	UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
	[button setTitle:title forState:UIControlStateNormal];
	[button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
	button.titleLabel.font = [UIFont boldSystemFontOfSize:12];
	button.titleLabel.shadowColor = [UIColor colorWithWhite:0 alpha:0.5];
	button.titleLabel.shadowOffset = CGSizeMake(0, -1);
	button.frame = CGRectMake(0, 0, width, 30);
 
	UIImage *image = [[UIImage imageNamed:@"BarButton"] stretchableImageWithLeftCapWidth:5 topCapHeight:0];
	[button setBackgroundImage:image forState:UIControlStateNormal];
 
	return (self = [self initWithCustomView:button]);
}
 
@end

In the “Shared” folder you will also find images for the UINavigationController back button (named UITintedBackButtonXXX.png), but be advised that bar button items with a custom view won’t work on UINavigationItem’s backBarButtonItem property. You’ll have to put your custom back button on leftBarButtonItem instead.

Tip: If you also want to have Retina-sized images, run Artwork Extractor on a Retina device or on the Simulator in Retina mode. It’s very enlightening to look through the rest of the extracted artwork as well.