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:

- (void)tableView:(UITableView *)tableView
    moveRowAtIndexPath:(NSIndexPath *)fromIndexPath
    toIndexPath:(NSIndexPath *)toIndexPath
{
    // Update the model with the change.
    // The view updates are already handled by UIKit.
}

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.

How to Keep Your Protocols Private

Don’t you just hate when a small change in the innards of your view controller forces you to change its header file just to conform to a delegate protocol? For example, adding emailing functionality requires you to implement the MFMailComposeViewControllerDelegate protocol and @import <MessageUI/MessageUI.h>. Talk about breaking encapsulation…

Thankfully, you can do that in your .m implementation file instead. (Even though Apple sample code doesn’t.) All you need to do is use the empty category:

// MyViewController.m
#import "MyViewController.h"
#import 

@interface MyViewController ()
     // privately conform to protocol
@property (nonatomic, strong) UIView *somePrivateSubview;
@end

@implementation MyViewController
// synthesize and methods implementations
@end

The empty category MyViewController () allows you to define private ivars, properties, methods, and even protocols – all in the privacy of your .m file, transparent to your clients.

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:

#import  // don't forget!
// ...
UILabel *badge = [[UILabel alloc] init];
badge.layer.backgroundColor = [UIColor blueColor].CGColor;
badge.layer.cornerRadius = badge.bounds.size.height / 2;

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:

#import "UIView+RenderUIImage.h"
#import 

@implementation UIView (RenderUIImage)

- (UIImage *)renderAsImage
{
    // setup context
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0f); // use same scale factor as device
    CGContextRef c = UIGraphicsGetCurrentContext();

    // render view
    [self.layer renderInContext:c];

    // get reslting image
    UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return result;
}

@end

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

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:

person.thumbnailImage = [UIImage imageNamed:@"defaultPortrait"];
anImageView.image = person.thumbnailImage;