macdevcenter.com
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

Adding a Preferences Window to Your Application
Pages: 1, 2, 3, 4, 5, 6, 7

Setting the initial state of the check boxes

One other thing we need to do is set the initial states of the check boxes to match those columns put in the table by initializeTableWithColumns. We could easily do this in the initializeTableWithColumns: method, within the second enumeration, in the following manner:

- (void)initializeTableWithColumns:(NSArray *)identifiers
{
  NSEnumerator *e;
  id column, identifier;
  NSTableColumn *column;

  // clear out the existing columns in tableView
  e = [[tableView tableColumns] objectEnumerator];
  while ( (column = [e nextObject]) ) {
    [tableView removeTableColumn:column];
  }

  // add columns from the argument array
  e = [identifiers objectEnumerator];
  while ( (identifier = [e nextObject]) ) {
    column = [tableColumns objectForKey:identifier];
    [tableView addTableColumn:column];

    if ( [identifier isEqualToString:@"First Name"] )
      [firstNameCB setState:NSOnState];
    if ( [identifier isEqualToString:@"Last Name"] )
      [lastNameCB setState:NSOnState];
     // And so on with the other four check boxes.
  }
}

So you see, each time through the while loop, we check to see which column we're adding using NSString's isEqualToString:, and then set the state of the appropriate check box to NSOnState.

As always, however, we can vastly improve upon the way we handle this. One way we could do this is to create a dictionary with a set of keys that are the column identifiers, and the corresponding values being the six check box outlets. The following table shows what this dictionary will look like.

Key Value
@"First Name" firstNameCB
@"Last Name" lastNameCB
@"Email" emailCB
@"Home Phone" homePhoneCB
@"Work Phone" workPhoneCB
@"Mobile Phone" mobilePhoneCB

We'll call this dictionary checkBoxes, declaring it in Controller.h

NSDictionary *checkBoxes;

And then we can use this in initializeTableWithColumns: in the second enumeration as follows:

// add columns from the argument array
e = [identifiers objectEnumerator];
while ( (identifier = [e nextObject]) ) {
  column = [tableColumns objectForKey:identifier];
  [tableView addTableColumn:column];
  [[checkBoxes objectForKey:identifier] setState:NSOnState];
}

And you see how the series of if statements has been replaced by the one line. Before we can use this, however, we have to initialize checkBoxes in awakeFromNib. We will do this by using the NSDictionary method dictionaryWithObjects:forKeys:. This method takes two NSArray arguments, both of which must have the same number of elements. The first argument will be an array of checkBoxes, and the second argument will be the array of identifiers that we earlier obtained from the bundle resources. So this initialization requires that we first create an array of the check box outlets, and then use that in conjunction with the array identifiers to create a dictionary. Now order is important here -- the order of check boxes in the array must be the same as the order of strings in identifiers. Here is the code:

NSArray *checkBoxesArray;  // At the beginning of awakeFromNib,
                           //with the rest

checkBoxesArray = [NSArray arrayWithObjects:firstNameCB, lastNameCB, emailCB, homePhoneCB, workPhoneCB, mobilePhoneCB, nil];
checkBoxes = [[NSDictionary alloc] initWithObjects:checkBoxesArray forKeys:identifiers];

We're doing in four lines of code that which previously took twelve, and it is straightforward to include additional check boxes. So now we can access the check boxes by column identifier.

We're not yet done with this section. We still haven't considered the possibility that the check boxes might need to be set outside of initializeTableWithColumns:, specifically in the case that there was no preference for the key @"User Columns". Recall the code in awakeFromNib where we checked for this:

if ( [prefs arrayForKey:@"User Columns"] != nil ) {
  userColumns = [[NSMutableArray alloc] initWithArray:[prefs arrayForKey:@"User Columns"]];
  [self initializeTableWithColumns:userColumns];
} else {
  userColumns = [[NSMutableArray alloc] init];
}

Remember that when this particular preference is not present in the defaults database, this if statement will evaluate to "false", and we will simply initialize userColumns to an empty dictionary. Now that we're dealing with the initial states of the check boxes, we have another thing to worry about in the else block -- the default states of the buttons, to match the default configuration of the table. In our case, the default columns are First Name, Last Name, Email, and Home Phone, so we have to set the states of those check boxes to NSOnState:

if ( [prefs arrayForKey:@"User Columns"] != nil ) {
  userColumns = [[NSMutableArray alloc] initWithArray:[prefs arrayForKey:@"User Columns"]];
  [self initializeTableWithColumns:userColumns];
} else {
  userColumns = [[NSMutableArray alloc] init];
  [firstNameCB setState:NSOnState];
  [lastNameCB setState:NSOnState];
  [emailCB setState:NSOnState];
  [homePhoneCB setState:NSOnState];
}

Another possibility for this would have been to leave the code as it was, and simply build the interface so that these four buttons are on by default. The choice is yours.

Pages: 1, 2, 3, 4, 5, 6, 7

Next Pagearrow