Dec 2, 2008

Riding the Livestrong Challenge. Asking you for a contribution.

Hello friends-

As many of you know my life has been profoundly affected by cancer. Four years ago my dear former wife Susan died from metastatic breast cancer after a 15 year on and off battle with the disease. I was with her and held her hand as she passed. Just one year ago, my mother also died due to lung cancer after fighting for a couple of years herself. She had never smoked a day in her life. I know that many of you have faced this terrible disease either yourself or in your family. Everyone is or will be affected by this disease at some point in their life.

One of my favorite bloggers, Elden Nelson of fatcyclist.com is now facing the same battle with his wife also named Susan. His situation is remarkably similar to mine of four years ago. His Susan has had her cancer spread to her bones and her brain and she is on steroids and receiving oxygen. The many rounds of Chemotherapy have failed to eradicate the disease. She is now in hospice care.

Elden has decided to form a team to join the Livestrong Challenge. His goal is to raise over 1 million dollars for cancer research. We may not get a cure right away but we can strike a blow. I have decided to join with Elden and his Team Fatty in this year’s event in San Jose California. I plan on riding my bike the full 100 miles. We want to be the largest team in Livestrong history and raise the most money we can.

As part of this effort I’m asking you to give me a hand at raising as much money as possible. Please consider donating $25 or more to my effort on my personal page. I am planning on matching whatever amount I get personally, and then my employer, Google, will match me up to $3000. So, you can see that your donation will be multiplied by a factor of 3.

Thanks for your consideration in helping me in this effort.

Paul

Oct 30, 2008

Police nab bicycle thief thanks to stupidity.

This is a little different type of post for me, but last week I had three bicycles stolen from my locked storage unit at my apartment building here in San Francisco. Thanks to some quick thinking by one of Stacie's employees and a bit of finagling on my part, we were able to arrange for the "alleged" thief to get arrested and for me to recover at least one of the bikes. Instead of reposting the whole story I'd like to refer you to my daughter's blog: http://ilovelladro.blogspot.com/2008/10/sting-at-google.html

Oct 12, 2008

Organizing a complex UITableView with the iPhone SDK by using a dispatch table

Hi. I've been working on an iPhone SDK application for a while, and one major piece of this application is a fairly complex table view. The UITableView is the workhorse class of most iPhone applications - you see it everywhere. One problem with the table view is that the controller class tends to get very large and complex, especially if you have a multiple section table view that has different types of custom cells and behaviors. There are many things that can be done to make this job easier. One excellent technique was recently documented by Frasier Speirs: A technique for using UITableView and retaining your sanity.

I've developed a technique that can make use of this technique but that goes beyond it by allowing you to delegate the handling of each section in a table view to its own class. It is also easily configurable if you need to add or remove a section type from your controller later, and allows you to localize your changes so that you don't have to remember to modify code in several places.


As I'm sure many of you know, the UITableViewDelegate protocol contains about 16 methods that take either an NSIndexPath object that specifies a row in a specific section, or an NSInteger that specifies a section.

The most obvious way to implement this would be through a switch statement in each of these methods. In the case of my program, this rapidly became unworkable, since I have 5 different sections, some with their own custom view types and specific logic for each section that uses a different portion of the data model and logic to generate the table view.


The basis of my technique is to create a main view controller for the table view, in this case called NoteViewController, and separate section controllers for each section that inherit from an AbstractNoteSectionController class that I created. This class defines the interface for the section controllers and provides reasonable default behavior in case I don't need specific behavior in my subclasses. The interface for this class is:

@interface AbstractNoteSectionController: NSObject {
NSUInteger section;
NoteViewController *parent;
}

@property NSUInteger section;
@property (nonatomic,retain) NoteViewController *parent;

- (id)initWithNoteViewController:(NoteViewController *)cnt
                      andSection:(NSUInteger)aSection;

- (NSUInteger)numberOfRows;

- (UITableViewCell *)cellForRow:(NSUInteger)row;

- (UITableViewCellEditingStyle)editingStyleForRow:
   (NSUInteger)row;

- (void)selectedRow:(NSUInteger)row
    withEditingStyle:(UITableViewCellEditingStyle)style;

- (void)commitEditingStyle:(UITableViewCellEditingStyle)style
                    forRow:(NSUInteger)row;

- (BOOL)canEditRow:(NSUInteger)row;

- (BOOL)shouldIndentWhileEditingRow:(NSUInteger)row;

@end

I've only implemented the table view delegate methods that I need for my application. I then subclass this and implement the specific functionality for each section in a separate subclass. In the main NoteViewController class, I have a sectionDict instance variable that has an NSDictionary object keyed by the section number:

// Build a dispatch table so we can more
// easily navigate all the sections.
- (NSMutableDictionary *)buildSectionDict {
  return [NSMutableDictionary dictionaryWithObjectsAndKeys:
    [[[FirstSectionController alloc]
      initWithNoteViewController:self
                      andSection:FIRST_SECTION] autorelease], 
    [NSNumber numberWithUnsignedInteger:FIRST_SECTION],
...
    [[[LastSectionController alloc]
      initWithNoteViewController:self
                      andSection:LAST_SECTION] autorelease],
    [NSNumber numberWithUnsignedInteger:LAST_SECTION], nil];
}

Then, I have a method to select the section controller given a section:
- (AbstractNoteSectionController *)
    sectionControllerForSection:(NSUInteger)aSection {
  NSNumber *section =
    [NSNumber numberWithUnsignedInteger:aSection];
  return (AbstractNoteSectionController *)
    [sectionDict objectForKey:section];
}
After this, something like tableView:numberOfRowsInSection: is reduced to this simple piece of code from a fairly complex and difficult to maintain switch statement:

- (NSInteger)tableView:(UITableView *)tableView
  numberOfRowsInSection:(NSInteger)section {
  return [[self sectionControllerForSection:section]
    numberOfRows];
}

This allows each section controller to be focused and readable. For example, the numberOfRows method for the PhotosSectionController is very simple.

- (NSUInteger)numberOfRows {
  return ((self.cameraAvailable) ? 2 : 1) +
      [parent.note countOfPhotos];
}

I suppose that I should mention at this point that each section controller has a parent member that points to the NoteViewController which still mediates access to the model (parent.note)


I love programming with this type of dispatch table. It makes for extremely flexible code that is not at all brittle, because I can add or remove sections from the table view by simply editing the buildSectionDict method and writing a new subclass of AbstractNoteSectionController.  No other methods of the NoteViewController ever have to change, which is great because it gives me fewer things to think about.

Using this technique, I was able to split up a hard to read and manage 700 line behemoth class into much more managable 80-200 line pieces and improve the readability and flexibilty of my code immensely. Hope you find this useful in your iPhone development.

Jul 30, 2008

Frustration over iPhone SDK NDA

Just a short post. I wanted to express my frustration over the situation with the iPhone SDK and the NDA. I've been itching to start posting about iPhone development for a while now, and figured that I'd be able to do so as soon as iPhone OS 2.0 shipped. Here's hoping that Apple will make the decision to lift it soon. 

Some links about this topic:


These are just two of many. Come on, Apple allow us to blog, write books and discuss the SDK. The community will grow and you'll get better apps.

Mar 28, 2008

Possible Interface Builder bug with QCView in Leopard


A friend of mine was trying to embed a Quartz Composer composition into a Cocoa app, and he was having problems getting it to work properly. The composition responded to mouse events and it worked just fine within QC, but for some reason not within a QCView. I took a look at the project and he had done everything right, as far as I could tell; the "ForwardAllEvents" checkbox was checked. 

So, I decided to perform a little experiment. I added a view controller to the application with the QCView as an outlet.

Lo and behold, the eventForwardingMask was set to 1, not NSAnyEventMask as it should have been. The solution then presented itself: Set this value correctly in the -awakeFromNib and now the application worked properly
Here's the header file:

#import <cocoa/cocoa.h>
#import <quartzcomposer/qcview.h>

@interface MyViewController : NSObject {
IBOutlet QCView *myView;
}

@end

And here's the implementation:

#import "MyViewController.h"

@implementation MyViewController

- (void)awakeFromNib
{
NSLog(@"%d", [myView eventForwardingMask]);
[myView setEventForwardingMask:NSAnyEventMask];
NSLog(@"%d", [myView eventForwardingMask]);
}

@end

I'm going to file a bugreporter bug right away.