I have this cellForRowAtIndexPath method here:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if (cell.accessoryView == nil) {
cell.accessoryView = [[Checkbox alloc] initWithFrame:CGRectMake(0, 0, 25, 43)];
cell.accessoryView.opaque = NO;
cell.backgroundColor = [UIColor clearColor];
[(Checkbox*)cell.accessoryView addTarget:self action:#selector(checkBoxTapped:forEvent:) forControlEvents:UIControlEventValueChanged];
}
NSString *sectionTitle = [contactSectionTitles objectAtIndex:indexPath.section];
NSArray *sectionContacts = [contactDirectoryFinal objectForKey:sectionTitle];
NSString *contacts = [[sectionContacts objectAtIndex:indexPath.row] valueForKey:#"item"];
cell.textLabel.text = contacts;
[(Checkbox*)cell.accessoryView setChecked: [[[sectionContacts objectAtIndex:indexPath.row] valueForKey:#"checkedItem"] boolValue] ];
return cell;
}
inside this method, I have this line:
[(Checkbox*)cell.accessoryView addTarget:self action:#selector(checkBoxTapped:forEvent:) forControlEvents:UIControlEventValueChanged];
which calls this method
- (IBAction)checkBoxTapped:(id)sender forEvent:(UIEvent*)event
{
}
What I am trying to do is adjust the way this method is called so I am also passing int the indexPath.row number
I got started with this:
[(Checkbox*)cell.accessoryView addTarget:self action:#selector(checkBoxTapped:forEvent:rowNumber:) forControlEvents:UIControlEventValueChanged];
and this
- (IBAction)checkBoxTapped:(id)sender forEvent:(UIEvent*)event rowNumber:(int)row
{
}
but I am new to selectors, my question is where do I pass in the rowNumber?
As you've found out you can't pass just any values with your selector, only the sender and the event. This is why you need another way pass the row number.
One method is to use the tag property on your control and retrieve it with [sender tag], however this approach will fail if the table indexes are changed without cellForRowAtIndexPath being called. It also won't work for sectioned table views.
A more robust approach is to use the location of your view to calculate the correct row. UITableView has a convenient method to do this:
- (IBAction)checkBoxTapped:(id)sender forEvent:(UIEvent*)event {
CGPoint checkBoxPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:checkBoxPosition];
}
As an alternative to passing it in ....
func checkBoxTapped(sender: CheckBox, withEvent event: UIEvent) {
if let tap = event.allTouches()?.first {
let location = tap.locationInView(tableView)
let indexPath = tableView.indexPathForRowAtPoint(location)
..... do something
}
}
*Update
As #Maddy 's comment
Do not use tag to represent the indexPath. It fails if the table view allows any rows to be moved, inserted, or deleted
this is not a good answer.*
As CheckBox is a UIView you can set its tag in cellForRowAtIndexPath: and then check for it in checkBoxTapped:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if (cell.accessoryView == nil) {
cell.accessoryView = [[Checkbox alloc] initWithFrame:CGRectMake(0, 0, 25, 43)];
cell.accessoryView.opaque = NO;
cell.backgroundColor = [UIColor clearColor];
[(Checkbox*)cell.accessoryView addTarget:self action:#selector(checkBoxTapped:forEvent:) forControlEvents:UIControlEventValueChanged];
}
NSString *sectionTitle = [contactSectionTitles objectAtIndex:indexPath.section];
NSArray *sectionContacts = [contactDirectoryFinal objectForKey:sectionTitle];
NSString *contacts = [[sectionContacts objectAtIndex:indexPath.row] valueForKey:#"item"];
cell.textLabel.text = contacts;
[(Checkbox*)cell.accessoryView setChecked: [[[sectionContacts objectAtIndex:indexPath.row] valueForKey:#"checkedItem"] boolValue] ];
// set the index to the tag.
cell.accessoryView.tag = indexPath.row
return cell;
}
- (IBAction)checkBoxTapped:(id)sender forEvent:(UIEvent*)event
{
// get the index from the tag value
NSInteger row = ((UIView *)sender).tag
}
You could use:
- (NSIndexPath *)indexPathForCell:(UITableViewCell *)cell
once you have the UITableViewCell object which can be accessed as sender.superview
Related
Here I am trying to do dynamic UITableViewCell with UIPickerView.
Step 1:
In Custom cell, I took 1 label and 1 UITextField.
Step 2:
used downpickerview library for data displaying and data fetching.
Step 3:
using below code I can able to select data, but after that, if I scroll UITableView data will be miss placing.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"Cell";
customCell *cell1=[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell1 == nil)
{
cell1 = [[customCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
}
cell1.productTitleLabel.text =[arrProductTitle objectAtIndex:indexPath.row];
self.downPicker = [[DownPicker alloc] initWithTextField:cell1.productvalueTextfield withData:arrProductVal];
[self.downPicker addTarget:self action:#selector(measurementSelected:) forControlEvents:UIControlEventValueChanged];
[cell1.contentView addSubview:self.downPicker];
return cell1;
}
Please help me on this.
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = #"DETAILS";
_dict = [[NSMutableDictionary alloc]init];
arrProductTitle = [[NSMutableArray alloc]initWithObjects:#"title0",#"title1",#"title2",#"title3",#"title4",#"title5",#"title6",#"title7",#"title8",#"title9",#"title10",#"title11",#"title12",#"title13",#"title14",#"title15", nil];
arrProductVal = [[NSMutableArray alloc]initWithObjects:#"0",#"1",#"2",#"3",#"4",#"5",nil];}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return arrProductTitle.count-1;}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *MyIdentifier = #"Cell";
customCell *cell1=[tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell1 == nil)
{
cell1 = [[customCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier];
}
cell1.productTitleLabel.text =[arrProductTitle objectAtIndex:indexPath.row];
NSLog(#"%#",_dict);
NSLog(#"%#",[NSString stringWithFormat:#"%ld",(long)indexPath.row]);
if (_dict[[NSString stringWithFormat:#"%ld",(long)indexPath.row]]) {
cell1.productvalueTextfield.text =[_dict valueForKey:[NSString stringWithFormat:#"%ld",(long)indexPath.row]];
}
else {
cell1.productvalueTextfield.text = #"";
self.downPicker = [[DownPicker alloc] initWithTextField:cell1.productvalueTextfield withData:arrProductVal];
self.downPicker.tag = indexPath.row;
[self.downPicker addTarget:self action:#selector(measurementSelected:) forControlEvents:UIControlEventValueChanged];
[cell1.contentView addSubview:self.downPicker];
}
return cell1;}
-(void)measurementSelected:(id)dp {
NSString* selectedValue = [dp text];
NSString* selectedIndex = [NSString stringWithFormat:#"%ld",(long)[dp tag]];
[_dict setValue:[dp text] forKey:selectedIndex];
NSLog(#"_dict: %#",_dict);
NSLog(#"SELECTED TAG:::::::%ld",[dp tag]);
NSLog(#"SELECTED VALUE:::::::%#",selectedValue);
NSLog(#"SELECTED INDEX VALUEEEEEEEEEEE:::::::%ld",[dp selectedIndex]);}
https://github.com/gvniosdev/Dynamic-UItableview-with-Picker-Selection
UITableViewCell values are misplacing because you haven't set the data for other cells, You need to store the values in an array and just update the values from there and it will work. :)
Something is not right with your code:
cell1.productTitleLabel.text =[arrProductTitle objectAtIndex:indexPath.row];
self.downPicker = [[DownPicker alloc] initWithTextField:cell1.productvalueTextfield withData:arrProductVal];
[self.downPicker addTarget:self action:#selector(measurementSelected:) forControlEvents:UIControlEventValueChanged];
[cell1.contentView addSubview:self.downPicker];
Bear in mind that in iOS, a tableView will reuse its cells. So when you scroll your UITableView, it will reuse the old cells which were created before, and
[cell1.contentView addSubview:self.downPicker]; Will be executed everytime a cell is reused, as a result, you will end up having many downPicker objects in one cell.
I am having custom-cell in which i put the UIButton as the CheckBox.
I want the array of selected checkBox indexPath in ViewController.
I am trying to set the UIButton Action event into the ViewController but it is not accessible. Here is my Code,
-(UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTableViewCellSaveSearchTableViewCell *cell = [tableView1 dequeueReusableCellWithIdentifier:#"SaveSearchCell"];
if(!cell)
{
cell = [[[NSBundle mainBundle]loadNibNamed:#"CustomTableViewCellSaveSearchTableViewCell" owner:self options:nil]objectAtIndex:0];
}
[self setText:cell];
[cell.btnDelete addTarget:self action:#selector(btnClick:) forControlEvents:UIControlEventTouchUpInside];
cell.btnDelete.tag = indexPath.row;
return cell;
}
-(void)btnClick : (UIButton *)btn
{
// I Can't accaes this method.
}
How can i get this.
UITableViewCells have a state of their own to reflect if they are selected or not. You don't need a button in the cells (it is discouraged for UX reasons anyway). Check here for a tutorial.
Do according to these three floowing method.
- (void)viewDidLoad {
[super viewDidLoad];
chekMarkArray = [[NSMutableArray alloc]init];
int totalData = 10;
chekMarkArray=[[NSMutableArray alloc] initWithCapacity:totalData];
for (int i=0; i<totalData; i++) {
[chekMarkArray addObject:#(0)];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
UIButton *testButton;
if (cell == nil ||1) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
testButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
testButton.frame = CGRectMake(100, 5,25, 25);
testButton.tag = indexPath.row;
BOOL selectindex = [[chekMarkArray objectAtIndex:indexPath.row] boolValue];
if (!selectindex) {
testButton.backgroundColor = [UIColor greenColor];
}else{
testButton.backgroundColor = [UIColor redColor];
}
[testButton addTarget:self action:#selector(DropDownPressed:) forControlEvents:UIControlEventTouchDown];
[cell addSubview:testButton];
}
return cell;
}
checked button action
-(void)btnClick : (UIButton *)btn
{
UIButton *button = (UIButton*)sender;
BOOL currentStatus = [[chekMarkArray objectAtIndex:button.tag] boolValue];
//deselect all selection
for (int i=0;i<chekMarkArray.count;i++) {
[chekMarkArray replaceObjectAtIndex:i withObject:#(0)];//comment this line for multiple selected button
}
//select current button
[chekMarkArray replaceObjectAtIndex:button.tag withObject:#(!currentStatus)];
[self.tableView reloadData];
}
You may use this code instead of button
first Alloc NsmutableArray in ViewDidLoad
and put an Button outside Tableview to complete your action.
then add
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if(cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[selectedRowsArray addObject:[arrShareTickets objectAtIndex:indexPath.row]];
}
else {
cell.accessoryType = UITableViewCellAccessoryNone;
[selectedRowsArray removeObject:indexPath];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *simpleTableIdentifier = #"CustomCell";
cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCell" owner: self options: nil ];
cell = [nib objectAtIndex:0];
}
//cell.lblName.text = [items objectAtIndex:indexPath.row];
NSMutableDictionary *dic = [items objectAtIndex:indexPath.row];
cell.imgface.image = [dic objectForKey:#"Image"];
cell.imgface.layer.cornerRadius = cell.imgface.frame.size.width / 2;
cell.imgface.layer.borderWidth = 3.0f;
cell.imgface.layer.borderColor = [UIColor whiteColor].CGColor;
cell.imgface.clipsToBounds = YES;
cell.lblName.text = [dic objectForKey:#"Name"];
[cell.btnPhone setTitle:[dic objectForKey:#"Phone"] forState:(UIControlStateNormal)];
cell.btnPhone.tag = indexPath.row;
cell.btnstar.tag = indexPath.row;
[cell.btnPhone addTarget:self action:#selector(dial:) forControlEvents:(UIControlEventTouchUpInside)];
[cell.btnstar addTarget:self action:#selector(toggleimage:) forControlEvents:UIControlEventTouchUpInside];
if (indexPath.section == 0)
{
star = [UIImage imageNamed:#"Star-Favorites.png"];
[cell.btnstar setBackgroundImage:star forState:UIControlStateNormal];
}
else
{
star = [UIImage imageNamed:#"keditbookmarks.png"];
[cell.btnstar setBackgroundImage:star forState:UIControlStateNormal];
}
return cell;
}
write below code in button IBAction and you will get indexpath.row and indexpath.section
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
NSLog(#"selected tableview row is %d",indexPath.row);
You have some different ways to do that:
• When you configure the cell set the tag of the cell or the button as the row and retrieve that on the IBAction (I hate tags though)
• Define a delegate for the table cell and set it when you configure it. Then call the delegate method passing the cell and find the relative index (-indexPathForCell:)
• The same as before but pass the cell through a notification instead of delegates
first of all on, button IBAction call this method
- (IBAction)btnClick:(UIButton)sender
{
UITableViewCell *cellOfcontrol=[self cellWithSubview:sender];
NSIndexPath *indexPath = [self.tableview indexPathForCell:cellOfcontrol];
}
cellWithSubview function
- (UITableViewCell *)cellWithSubview:(UIView *)subview
{
while (subview && ![subview isKindOfClass:[UITableViewCell self]])
subview = subview.superview;
return (UITableViewCell *)subview;
}
I've been trying to figuered this out for hours. I'm just plain old stuck here. What im trying to accomplish is basically inserting a row directly below the row just tapped in the tableview in addition i would like to add and image to the row and and make the image clickable to respond to its click event.
So here is my code.
I implemented (i belive) the nessesary methods to handle all the actions for the uitableview.
when the user taps the cell i handle that action by executing the following code.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (debug==1) {
NSLog(#"running line 225%# '%#'", self.class, NSStringFromSelector(_cmd));
}
Locations *location = nil;
Locations *tempObject = [[Locations alloc]init];
//test to see if we are looking for the search box or if we are essentially looking from the main view controller.
if (self.searchDisplayController.active) {
location= [self.searchResults objectAtIndex:indexPath.row];
NSLog(#"location : %#" ,location.locationName);
} else {
location = [self.locations objectAtIndex:indexPath.row];
NSLog(#"location : %#" ,location.locationName);
//set the new indexpath to 1 more then before so that we can essetially add a row right below the actual tapped item.
NSIndexPath *newPath = [NSIndexPath indexPathForRow:indexPath.row + 1 inSection:indexPath.section];
indexPath = newPath;
[self.locations insertObject:tempObject atIndex:indexPath.row ];
[tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationBottom];
self.visibleCell =YES; //set this boolean variable so that we can add a specific row image to this var
// self.locations[0].isItVisible = YES;
}//ends the else statement.
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
the above code inserts an empty cell into my tableview.
however how can i set the cell so that its custom and not the same as the others. In other words my initial cells data-source are basically bound to an nsobject and a string property location-name. However when i go try to update the table cells in the above method i obviously cannot add an image into a string so I'm running in to a error.
so i tried to instead make the update on the
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
by basically checking if a variable is set to true or false but that turned out to be buggy because even when i scroll this method gets called.
How should i go about doing this. I think i have to do it all in the didselectrowindexaspath method. But i cant figured out how to change the newly inserted cell to contain an image only.
Any help would be appreciated.
EDIT
here is what im doing to try to add the image under the cellforrowindexpath method.
if(self.visibleCell==YES){
UIImage *clkImg = [UIImage imageNamed:#"alarm_clock.png"];
cell.imageView.image = clkImg;
}
Im a noob so im not sure im doing this correctly.
EDIT
this is the full cellforatindexpath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (debug==1) {
NSLog(#"running line 159 %# '%#'", self.class, NSStringFromSelector(_cmd));
}
// NSLog(#"cell for row at index path just got called");
//JAMcustomCell *myCell = [[JAMcustomCell alloc]init];
static NSString *CellIdentifier = #"ListPrototypeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Locations * locations = [[Locations alloc]init];
//tableView.backgroundColor = [UIColor blackColor];
// NSLog(#"this is visible '%hhd'", locations.isItVisible);
if(self.visibleCell==YES){
UIImage *clkImg = [UIImage imageNamed:#"alarm_clock.png"];
cell.imageView.image = clkImg;
}
if (tableView == self.searchDisplayController.searchResultsTableView)
{
locations = [self.searchResults objectAtIndex:indexPath.row];
}
else{
locations = [self.locations objectAtIndex:indexPath.row];
}
cell.textLabel.text = locations.locationName;
cell.textLabel.textColor = [UIColor whiteColor];
//cell.backgroundColor =[UIColor blackColor];
// cell.backgroundColor =[UIColor colorWithPatternImage:[UIImage imageNamed:#"Graytbl.fw.png"]];
cell.backgroundView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"blueTbl.fw.png"]];
cell.selectedBackgroundView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"blueTbl.fw.png"]];
// UIFont *myFont = [ UIFont fontWithName: #"Oswald" size: 25.0 ];
// cell.textLabel.font = myFont;
cell.textLabel.font= self.MyFont;//[UIFont fontWithName:#"Oswald-Regular.ttf" size:15];
return cell;
}
Try this approach, I used your idea of Bool
#pragma mark - Table View Data Source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.numberOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(self.visibleCell){
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"imageViewCell" forIndexPath:indexPath];//ListPrototypeCell
UIImageView *imageVIew = (UIImageView *)[cell viewWithTag:1];
[imageVIew setImage:[UIImage imageNamed:#"alarm_clock.png"]];
return cell;
}else{
return [tableView dequeueReusableCellWithIdentifier:#"ListPrototypeCell" forIndexPath:indexPath];
}
}
#pragma mark - Table View Delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if(!self.visibleCell){
self.numberOfRows++;
self.visibleCell = YES;
NSIndexPath *indexPathCell = [NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPathCell] withRowAnimation:UITableViewRowAnimationBottom];
}else{
self.numberOfRows--;
self.visibleCell = NO;
NSIndexPath *indexPathCell = [NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0];
[self.tableView deleteRowsAtIndexPaths:#[indexPathCell] withRowAnimation:UITableViewRowAnimationTop];
}
}
I created a demo project for you.
I hope it helps
I have a question about the event value changed for UISwitch, here is my problem in detail.
in numberOfRowsInSection i have loop that calls the a data base method which return #of rows for each section.
I used an array of arrays(BECAUSE OF I HAVE MANY SECTIONS WITH MANY ROWS) that keeps state of UISwitch then update it whenever value changed called, here is the code of the event:
HOWEVER, after all of these UISwitch still resets whenever I scroll up or down. PLEASE HELP ME AS SOON AS POSSIBLE I will appreciate YOUR HELP SOOOOO MUCH .
Thank you in advance.
I think you make logic error in if (sender.on) in -(void)switchChanged:(UISwitch *)sender method because when sender.on == YES you make OFF:) write
-(void)switchChanged:(UISwitch *)sender
{
UITableViewCell *cell = (UITableViewCell *)[sender superview];
NSIndexPath *x =[mainTableView indexPathForCell:cell];
NSMutableArray *repl = [SwitchArray objectAtIndex:x.section];
[repl replaceObjectAtIndex:x.row withObject:(sender.on ? #"ON", #"OFF")];
}
You can double check the value in the table view willDisplayCell: just to make sure you have it right:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
UISwitch* uiSwitch = (UISwitch*) cell.accessoryView;
if (uiSwitch != nil && [uiSwitch isKindOfClass:[UISwitch class]]) {
//just make sure it is valid
NSLog(#"switch value at %d-%d is: %#",indexPath.section, indexPath.row, [SwitchArray[indexPath.section] objectAtIndex:indexPath.row] );
uiSwitch.on = [[SwitchArray[indexPath.section] objectAtIndex:indexPath.row] isEqualToString:#"ON"];
}
}
As an aside, you can you use NSNumbers to make the code more readable:
-(void)switchChanged:(UISwitch *)sender
{
UITableViewCell *cell = (UITableViewCell *)[sender superview];
NSIndexPath *x=[mainTableView indexPathForCell:cell];
NSLog(#"%ld", (long)x.section);
//NSLog(#"index for switch : %d", switchController.tag );
NSMutableArray *repl = repl= [SwitchArray objectAtIndex:x.section];
repl[x.section] = #(sender.on);
}
Then where you set the on value:
uiSwitch.on = [[SwitchArray[indexPath.section] objectAtIndex:indexPath.row] boolValue];
Cells get reused. You are creating a new switch every time a cell is used. You should only create a switch once for each cell. Try the following in your cellForRow... method:
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
UISwitch *switchController = [[UISwitch alloc] initWithFrame:CGRectZero];
[switchController setOn:YES animated:NO];
[switchController addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = switchController;
[switchController release];
}
UISwitch *switch = cell.accessoryView;