The Simplest iOS Badge

SimplestBadgeLabel
In the past I used a UILabel subclass to show a badge. But since the dawn of flat UI, there’s no need to subclass.

Here is all the code you need:

All it does is set the cornerRadius of the label’s underlying CALayer, and add spaces before and after the label text. That’s it!

For nicely organized badge extension for UILabel and UIButton and UIBarButtonItem, see this GitHub gist:
Badge.swift

Simple UIProgressHUD replacement

The private API UIProgressHUD shows an activity indicator (spinner) over a shaded round rect. Although you can use fancy and flexible replacements like MBProgressHUD, there is a simpler way if you don’t need all the extra functionality: Take a regular UIActivityIndicatorView and add a partly transparent UIView behind it.

The simplest is to subclass of UIActivityIndicatorView so you can use it like any activity indicator.

The interface file:

And the implementation file:

To use, init the ActivityHUD in a view, and later call startAnimating to show it, and stopAnimating to hide.

Dynamic UIActionSheet

Some actions may sometimes have more than one possible target, and other times only one.

For example: Calling a contact. If the contact has just one phone number, you openURL with it and you’re done. But if she has several numbers, you want to open a UIActionSheet to let the user choose which number to call.

Or picking an image. If you’re running on a camera-less iPod, you just show a UIImagePickerController to pick from the photo library. But with a camera, and maybe an existing image to delete, you’ll want to show an action sheet to choose the actual action that your “Photo” button performs.

So you need to do two things:

  1. Decide whether to show an action sheet at all or just do the one possible action.
  2. If you need an action sheet, fill it dynamically with the possible targets for action.

The code to do that doesn’t have to be complicated. It can actually be as simple as this:

Notes:

  1. The @interface code above is part of the .m file, as described in my earlier post How to Keep Your Protocols Private.
  2. If you’re puzzled by the meaning of __(@"String") then see my earlier post on How To Make NSLocalizedString Fun To Use.
  3. The objects in possibleTargets can hold a selector (SEL) of the actual method to be executed, or they can hold just relevant data for the action (like a phone number to call).

Reordering a UITableView

I like the simple and straightforward interface of the Reminders.app: edit reminders inline, and add a reminder by tapping and typing in the next empty line. So I wrote a UITableViewController subclass that does just that, but adds Edit mode with reordering.

Coding reordering requires implementing methods from both of the two entangled protocols UITableViewDataSource and UITableViewDelegate.

In UITableViewDataSource we have the methods:
tableView:commitEditingStyle:forRowAtIndexPath: (for insert and delete)
tableView:canMoveRowAtIndexPath: (for reorder)
tableView:moveRowAtIndexPath:toIndexPath: (for reorder)

And in UITableViewDelegate:
tableView:editingStyleForRowAtIndexPath: (for insert and delete)
tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath: (for reorder)

The UITableViewDelegate methods are not strictly necessary in the simplest case where all rows are deletable, no row is insertable, and all rows are reorderable. In fact, in this simplest case you don’t need canMoveRowAtIndexPath either, only this:

But of course, if the last row (or the row past last) is an insert row, and is not reorderable, than you need to implement the other methods as well. You can get the code for that (along with the inline editable UITextField-s) at GitHub: http://github.com/yonat/EditableList.

BadgeLabel – Simple UILabel-based Badge

I know, I know – not another badge class! But the thing is, the other badges laying around the net all seem overly complicated and too inflexible. So yes, I wrote another badge class. Luckily, it was really easy because I used the built-in capabilities of iOS, and it turned out very flexible and powerful, because, well, I used the built-in capabilities of iOS. No manual CoreGraphics drawing code, just automatic CALayer-s magic.

The basic badge is a UILabel whose underlying CALayer has a backgroundColor and cornerRadius:

Basically, that’s it. There are some adjustments needed to make sure the label leaves enough space around the text for the rounded corners, but that’s easily done with short overrides of textRectForBounds and drawTextInRect.

The nice thing is how easy it is to make app-icon style badges, with border, shadow and gloss:

  • For border simply set the layer’s borderColor and borderWidth.
  • For shadow set the layer’s shadowOpacity, shadowColor and shadowOffset.
  • For gloss add a CAGradientLayer sublayer.

It’s that simple. And even better: animatable!

You can get the code, along with a Mail.app style BadgeTableViewCell and a demo app, at GitHub: http://github.com/yonat/BadgeLabel

Render UIView to UIImage

There’s a simple way to render a UIView into a UIImage: use the view’s layer, and render it into a bitmap graphic context. Here is the code, phrased as a UIView category:

Just remember to link the QuartzCore.framework and you’re good to go.

How To Make NSLocalizedString Fun To Use

To localize apps (which means: to make them work in other languages) you need to avoid using plain @”strings” and instead use the one of the tedious functions NSLocalizedString, NSLocalizedStringFromTable, or NSLocalizedStringFromTableInBundle, that take two to four arguments. Horror.

I mean, any sane programmer will get a headache from replacing a simple @"Great!" with this:

So I took a leaf from WordPress, and shortened the calls:

Now localization is easy and fun: I simply type __(@"Great!") and the localization code is taken care of by the C pre-processor. Mission accomplished.

Store UIImage in CoreData Without Writing Any Code

There is an easy but little known way to store many kinds of UIKit objects in CoreData without writing any code. It works for UIImage, UIColor, UIBezierPath, MKPlaceMark, NSDate, and any other class that conforms to the NSCoding protocol.

What you need to do is set the attribute type to Transformable.

That’s it!

Now can set UIImage objects directly into your NSManagedObject objects: