Handling multiple UISwitch controls in a table view without using the tag property

I have a table view controller with several UISwitch controls. I installed the delegate in the table view controller with the same action for all switches. I need to determine which switch was changed, so I create an array of strings that contains the name of each switch. Indexes in the array will be placed in the tag property of each UISwitch.

However, I am ready to use the tag property for something else, namely, to find the correct control in a cell in cellForRowAtIndexPath with viewWithTag! (A few things need to be set in each cell.)

So, am I thinking of the correct lines here? I feel that I'm pretty limited in how I find out which UISwitch has changed its value, so I can do something useful with it.

+6
objective-c iphone cocoa-touch uiswitch
source share
4 answers

I fixed this by subclassing UISwitch like this:

@interface NamedUISwitch : UISwitch { NSString *name; 

}

It seems elegant (without the necessary index arrays), and the tag property is free to do whatever it wants.

I read that you have to be careful with a subclass in Objective-C, though ...

+5
source share

I wrote a subclass of UISwitch with a block helper for change management events that can help when trying to keep track of what switch value has changed. Ideally, we could do something similar with composition rather than subclassing, but this works well for my needs.

https://gist.github.com/3958325

You can use it as follows:

 ZUISwitch *mySwitch = [ZUISwitch alloc] init]; [mySwitch onValueChange:^(UISwitch *uiSwitch) { if (uiSwitch.on) { // do something } else { // do something else } }]; 

You can also use it from an XIB file by dragging a switch to your view and then changing its class to ZUISwitch

+1
source share

You are approaching your approach. What I did in such situations was to create separate subclasses of UITableViewCell, set the UISwitch tag as index.row of the index path, and use this subclass of UITableViewCell only in a specific section of the table view. This allows you to use a cell tag to uniquely determine which cell has an event without supporting a separate index list (as it sounds, as if you are doing).

Since the cell type is unique, you can easily access other elements of the cell by creating methods / properties in a subclass of UITableViewCell.

For example:

 @interface TableViewToggleCell : UITableViewCell { IBOutlet UILabel *toggleNameLabel; IBOutlet UILabel *detailedTextLabel; IBOutlet UISwitch *toggle; NSNumber *value; id owner; } @property (nonatomic, retain) UILabel *toggleNameLabel; @property (nonatomic, retain) UILabel *detailedTextLabel; @property (nonatomic, retain) UISwitch *toggle; @property (nonatomic, retain) id owner; -(void) setLable:(NSString*)aString; -(void) setValue:(NSNumber*)aNum; -(NSNumber*)value; -(void) setTagOnToggle:(NSInteger)aTag; -(IBAction)toggleValue:(id)sender; @end 

IN:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // ... prior iniitalization code for creating cell is assumed toggleCell.owner = self; [toggleCell setLable:@"some string value"]; [toggleCell setTagOnToggle:indexPath.row]; toggleCell.owner = self; return toggleCell; //... handle cell set up for other cell types as needed } 

The owner is the delegate for the cell and can then be used to trigger actions in your controller. Make sure you connect your UISwitch to the toggleValue action so that you can trigger actions in the delegate when the UISwitch changes state:

 -(IBAction)toggleValue:(id)sender; { BOOL oldValue = [value boolValue]; [value release]; value = [[NSNumber numberWithBool:!oldValue] retain]; [owner performSelector:@selector(someAction:) withObject:toggle]; } 

By passing UISwitch by a method call, you can access the pointer path for the cell. You can also get around using the tag property by explicitly having ivar to store the NSIndexPath of the cell, and then pass the entire cell by a method call.

0
source share

I understand that I’m three years late for the party, but I developed a solution without a subclass, which I think is preferable (and easier). I work with the same script as the described Teyrin script.

 - (void)toggleSwitch:(id) sender { // declare the switch by its type based on the sender element UISwitch *switchIsPressed = (UISwitch *)sender; // get the indexPath of the cell containing the switch NSIndexPath *indexPath = [self indexPathForCellContainingView:switchIsPressed]; // look up the value of the item that is referenced by the switch - this // is from my datasource for the table view NSString *elementId = [dataSourceArray objectAtIndex:indexPath.row]; } 

Then you want to declare the method shown above, indexPathForCellContainingView. This seems to be an unnecessary method, because at first glance it seems that all you need to do is define a switch supervisor, but there is a difference between ios7 and earlier supervisors, so this handles everything:

 - (NSIndexPath *)indexPathForCellContainingView:(UIView *)view { while (view != nil) { if ([view isKindOfClass:[UITableViewCell class]]) { return [self.myTableView indexPathForCell:(UITableViewCell *)view]; } else { view = [view superview]; } } return nil; } 
0
source share

All Articles