Question

I have a UISwitch inside a custom UITableViewCell (the subclass of which I call RootLabeledSwitchTableCell).

The cell contains a UILabel and UISwitch next to each other.

I have a @property called keychainSwitch that points to the switch inside this custom cell:

@interface RootLabeledSwitchTableCell : UITableViewCell {
    IBOutlet UILabel *textLabel;
    IBOutlet UISwitch *labeledSwitch;
}

@property (nonatomic, retain) IBOutlet UILabel *textLabel;
@property (nonatomic, retain) IBOutlet UISwitch *labeledSwitch;

@end

In my table view delegate, I have added a selector that is called if the switch state is flipped:

- (UITableViewCell *) tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
   NSString *CellIdentifier = [NSString stringWithFormat: @"%d:%d", [indexPath indexAtPosition:0], [indexPath indexAtPosition:1]];
   UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:CellIdentifier];
   if (cell == nil) {
       switch (indexPath.section) {
       case(kMyFirstSection): {
           switch (indexPath.row) {
               case(kMyFirstSectionFirstRow) {
                   [cellOwner loadMyNibFile:@"RootLabeledSwitchTableCell"];
                   cell = (RootLabeledSwitchTableCell *)cellOwner.cell;
                   self.keychainSwitch = [(RootLabeledSwitchTableCell *)cell labeledSwitch];
                   [self.keychainSwitch addTarget:self action:@selector(keychainOptionSwitched) forControlEvents:UIControlEventValueChanged];
                   break;
               }
               // ...
           }
       }
       // ...
   }
}

So this selector works correctly:

- (void) keychainOptionSwitched {
   NSLog(@"Switched keychain option from %d to %d", ![self.keychainSwitch isOn], [self.keychainSwitch isOn]);
}

However, I cannot use the UISwitch instance's -setOn:animated: method to initialize its initial state:

- (void) updateInterfaceState {
   BOOL isFirstTimeRun = [[[NSUserDefaults standardUserDefaults] objectForKey:kIsFirstTimeRunKey] boolValue];
   if (isFirstTimeRun) {
      [self.keychainSwitch setOn:NO animated:NO];
   }
}

From testing, self.keychainSwitch is nil which is causing -setOn:animated to do nothing, but I can still operate the switch and the NSLog statement will correctly print the switch state changes, e.g.:

[Session started at 2009-08-24 07:04:56 -0700.]
2009-08-24 07:04:58.489 MyApp[29868:20b] keychain switch is: nil
2009-08-24 07:05:00.641 MyApp[29868:20b] Switched keychain option from 1 to 0
2009-08-24 07:05:01.536 MyApp[29868:20b] Switched keychain option from 0 to 1
2009-08-24 07:05:02.928 MyApp[29868:20b] Switched keychain option from 1 to 0

Is there something I am missing about setting self.keychainSwitch in the UITableView delegate method?

Was it helpful?

Solution

I did this a while ago. You should change your selctor

[self.keychainSwitch addTarget:self action:@selector(keychainOptionSwitched:) forControlEvents:UIControlEventValueChanged];

And then update your method to

-(void) keychainOptionSwitched:(id)sender {
UISwitch *tempSwitch = (UISwitch *)sender;
}

Now tempSwitch is the switch that was changed.

OTHER TIPS

I spent ages fiddling around with custom UITableViewCells with a simple label and switch on it before I discovered I could just add a UISwitch as an accessory view. You're probably aware of this anyway, and want the custom cell for other reasons, but just in case I wanted to mention this!

You do this as follows (in the -tableView:cellForRowAtIndexPath method):

UISwitch *mySwitch = [[[UISwitch alloc] initWithFrame:CGRectZero] autorelease];
cell.accessoryView = mySwitch;

The accessoryView bit also takes care of the sizing and positioning so we can get away with CGRectZero.

You're then able to use the system control event and setOn method as follows (note we cast it as the UISwitch pointer that we know it is):

[(UISwitch *)cell.accessoryView setOn:YES];   // Or NO, obviously!
[(UISwitch *)cell.accessoryView addTarget:self action:@selector(mySelector)
     forControlEvents:UIControlEventValueChanged];

Hope that helps!

I think whats happening here is that you are trying to invoke the operation when the cell is out of view, so whats going on is that the cell is unloaded at that time therefore you are getting a nil for the keychain switch, once it comes into view then its no longer nil since its reloaded. But i see that you are assigning the switch like so

 self.keychainSwitch = [(RootLabeledSwitchTableCell *)cell labeledSwitch];

Its a reference to the switch in the table cell and you are not retaining it, so it makes since that the switch is becoming nil since , when the cell goes out of view is unloaded and keychainSwitch is becoming nil as a result and therefore your class member is becoming nil as well. You might want to retain keychainSwitch and then when reconstructing your table c ell get the switch out of keychainSwitch, or something of the sort. Hope this helps

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top