Oct 09

Ok, this might seem like a simple thing to do – and in most cases it is, unless you’re using core data and have some row additions coming in dynamically.

- (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    cell.backgroundColour = (indexPath.row % 2) ? [Constants darkTableCellBackgroundColor] : [Constants lightTableCellBackgroundColor];
}

You see the problem I had was, that row zero is white, row one is blue, row two is white….etc, and when I synced with my remote server and new data arrived, it was inserted at row zero  - which is white! The other rows were pushed down, so row zero and row one were both white! No more alternate. I could have just refreshed the UITableView – or the visible rows, but I didn’t want to do that! I wanted it to figure out the correct row colour from the insert.

I got it working by combining the row index with the total rows, using the inverse of one and XOR’ing the result! Sounds complicated? Look at this table:

A: Row B: Row Modulus (%2) C: Row Count D: Count Modulus (%2) E: Inverse Count Modulus F: XOR B ^ E
0 0 6 0 1 1
1 1 6 0 1 0
2 0 6 0 1 1
3 1 6 0 1 0
4 0 6 0 1 1
5 1 6 0 1 0

As can be seen above, I can get alternate row colours from Column B or Column F. However, if you then add another row at index zero – the row modulus can no longer be used, but Column F, still preserves the alternate row colours!

A: Row B: Row Modulus (%2) C: Row Count D: Count Modulus (%2) E: Inverse Count Modulus F: XOR B ^ E
0 0 7 1 0 0
0 0 6 0 1 1
1 1 6 0 1 0
2 0 6 0 1 1
3 1 6 0 1 0
4 0 6 0 1 1
5 1 6 0 1 0

This can be achieved with this bit of code:

- (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    int rowFlag = (indexPath.row % 2);
    int totalFlag = [self tableView:tableView numberOfRowsInSection:indexPath.section] % 2;
    cell.backgroundColor = (rowFlag ^ !totalFlag) ? [Constants darkTableCellBackroundColor] : [Constants lightTableCellBackroundColor];
}

Let me know if I’ve missed something obvious here and there was a more common way of doing this.

written by admin \\ tags: , , ,

Nov 16

Doing some iPhone development and this error really caught me out for a while:

2009-11-16 21:02:48.387 Pickers[3779:207] *** Terminating app due to uncaught
exception 'NSUnknownKeyException', reason: '[<UIViewController 0x381d740>
setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key datePicker.'
2009-11-16 21:02:48.388 Pickers[3779:207] Stack: (

It’s seemed fairly cryptic at the time. I had created a Tab Bar Controller and for each tab button, i hadn’t set its class identity – so each tab was still declared as a UIViewController instead of the actual Controller class that i had created.

The error comes from the NSKeyValueCoding category which allows you to access properties via setValue: forKey:

Person *aPerson = [[Person alloc] initWithAge: 53];
aPerson.name = @"Steve";
// NOTE: dot notation, uses synthesized setter, equivalent to [aPerson setName: @"Steve"];
NSLog(@"Access by message (%@), dot notation(%@),
    property name(%@) and direct instance variable access (%@)",
      [aPerson name], aPerson.name, [aPerson valueForKey:@"name"], aPerson->name);

So i guess it is just complaining that it can’t find the generated setter method named setDatePicker – because datePicker instance is not on the generic class.

written by admin \\ tags: , ,