Weird behaviour with tableview and buttons - ios

I am trying to create a custom questionnaire. I have multiple NSMutableArray(btnAr) where I store the groups of buttons. To keep things in order, I use another NSMutableArray(radioGroupBtns) where I store all the NSMutableArrays(btnAr).
I use tableview to display the buttons. The problem I am facing is this:
When I click on a button in the first group, after scrolling to the last group the same button is clicked also.
The right image is when I scrolled at the bottom.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
-(UITableViewCell* )tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
FeedbackViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kCellIdentifier];
NSInteger rowNum = [indexPath row];
NSLog(#"RowNumb: %ld",rowNum);
NSMutableArray *btns = [radioGroupBtns objectAtIndex:rowNum];
NSMutableArray *lbls = [radioGroupLabels objectAtIndex:rowNum];
for (int i=0; i<[btns count]; i++)
{
[cell addSubview:[btns objectAtIndex:i]];
[cell addSubview:[lbls objectAtIndex:i]];
}
return cell;
}
-(void) getData
{
int totalSections = 5;
for (int j=0; j<totalSections; j++)
{
NSMutableArray *btnAr = [[NSMutableArray alloc]init];
NSMutableArray *lblAr = [[NSMutableArray alloc]init];
int numOfQuestions = 4;
for (int i=0; i<numOfQuestions; i++)
{
RadioUIButton *button = [self getButton:i];
button.sectionTag = j;
button.stringTag = [NSString stringWithFormat:#"%d%d", i,button.sectionTag];
[button setTag:i];
UILabel *lbl = [self getLabel:i text:#"Question"];
[lblAr addObject:lbl];
[btnAr addObject:button];
}
[radioGroupBtns addObject:btnAr];
[radioGroupLabels addObject:lblAr];
}
}
- (void) btnPressed:(id) b
{
RadioUIButton *btn = (RadioUIButton *) b;
NSMutableArray *group = [radioGroupBtns objectAtIndex:btn.sectionTag];
for (RadioUIButton *bn in group)
{
if ([bn tag] != [b tag])
{
if ([bn isSelected])
[bn setSelected:!bn.selected];
}
}
if (![btn isSelected])
[btn setSelected:!btn.selected];
NSLog(#"Button %ld clicked. Row: %d , String: %#", (long int)[b tag], btn.sectionTag, btn.stringTag);
}
- (RadioUIButton*) getButton:(int) i {
RadioUIButton *button = [RadioUIButton buttonWithType:UIButtonTypeCustom];
int hpos = i*30 + 30;
button.frame = CGRectMake(30.0f, hpos, 30.0f, 30.0f);
[button addTarget:self action:#selector(btnPressed:) forControlEvents:UIControlEventTouchUpInside];
//[button setTitle:#"Option A" forState:UIControlStateNormal];
[button setImage: [UIImage imageNamed:#"radio_button_off.png"]forState:UIControlStateNormal];
[button setImage: [UIImage imageNamed:#"radio_button_on.png"]forState: UIControlStateSelected];
return button;
}
- (UILabel*) getLabel:(int) i text:(NSString *) txt{
int hpos = i*30 + 30;
UILabel *label = [[UILabel alloc] init];
label.frame = CGRectMake(80,hpos,200,30);
label.text = txt;
return label;
}

Table view reuses cells. There are ways to handle this. But, in your case you dont seem to need to reuse cells. So use scroll view instead and inflate views inside that.
And as a suggestion, try to store model objects instead of buttons. Manipulate views and their state based on the data model.

Related

TableView CheckMarks

I Want to Put CheckMarks in tableview when selecting array of dictionaries data.
Ex:- Array contains 10 Model Names(It is Dictionary), It contains SubModels
My problem is,When I select Submodel, ModelName automatically get CheckMark.
Now I Put CheckMarks for different models & sub Models but how we can put checkmarks based on SubModels.
My cellForRow method
UITableViewCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
UILabel *nameLbl = (UILabel*) [cell.contentView viewWithTag:11];
UILabel *code = (UILabel*) [cell.contentView viewWithTag:12];
UIButton *button = (UIButton*) [cell.contentView viewWithTag:13];
NSInteger index = indexPath.row;
NSDictionary *dictParent = [_data objectAtIndex:indexPath.section];
NSDictionary *dictItem = dictParent;
if (indexPath.row > 0)
{
// If its not the first row in the section, assume the row is a child row.
NSArray *arrChildren = [dictParent objectForKey:#"ChildProductModels"];
// Get child row info
dictItem = [arrChildren objectAtIndex:indexPath.row ];
}
nameLbl.text = [dictItem objectForKey:#"Name"];
code.text = [dictItem objectForKey:#"Code"];
// To display checkmark for selected value
if (_selectedarray.count == _rowdata.count)
{
imagebutton.hidden=NO;
[headerArray removeAllObjects];
[headerArray addObject:#"1"];
UIImage *btnImage = [UIImage imageNamed:#"ic_floating_done_#1x"];
[button setImage:btnImage forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor colorWithRed:0/255.0 green:255/255.0 blue:255/255.0 alpha:1.0]];
}
else if ([_selectedarray containsObject:[_rowdata objectAtIndex:index]] )
{
imagebutton.hidden =NO;
[headerArray removeAllObjects];
[headerArray addObject:#"1"];
UIImage *btnImage = [UIImage imageNamed:#"ic_floating_done_#1x"];
[button setImage:btnImage forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor colorWithRed:0/255.0 green:255/255.0 blue:255/255.0 alpha:1.0]];
}
else
{
imagebutton.hidden=YES;
cell.accessoryType=UITableViewCellAccessoryNone;
UIImage *btnImage = [UIImage imageNamed:#""];
[button setImage:btnImage forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor whiteColor]];
}
From the above code I am Able to put checkmarks for multiple selection.Please give some idea (OR) example for My problem
(
{
ChildProductModels = (
{
Code = "LB3/7-002";
Name = "With transport apron 4.5 M";
ParentChildType = C;
ParentID = PMD000001;
ProductID = PRD000004;
ProductModelID = PMD000003;
},
{
Code = "LB3/7-003";
Name = "With Magnetic Roller";
ParentChildType = C;
ParentID = PMD000001;
ProductID = PRD000004;
ProductModelID = PMD000004;
}
);
Code = "LB3/7";
Name = "Mixing Bale Opener LB3/7";
ParentChildType = P;
ParentID = "<null>";
ProductID = PRD000004;
ProductModelID = PMD000001;
},
{
ChildProductModels = (
{
Code = "LB7/4-001";
Name = "With Beater";
ParentChildType = C;
ParentID = PMD000005;
ProductID = PRD000004;
ProductModelID = PMD000006;
}
);
Code = "LB7/4";
Name = "UNIMIX MODEL LB7/4";
ParentChildType = P;
ParentID = "<null>";
ProductID = PRD000004;
ProductModelID = PMD000005;
}
)
Above I put my array of dictionaries
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection: (NSInteger)section
{
Header *headerView = [tableView dequeueReusableCellWithIdentifier:#"HeaderView"];
UILabel *name = (UILabel*) [headerView.contentView viewWithTag:2];
UILabel *code = (UILabel*) [headerView.contentView viewWithTag:4];
name.text = [_data[section] valueForKey:#"Name"] ;
code.text=[_data[section] valueForKey:#"Code"] ;
imagebutton=(UIButton*)[headerView.contentView viewWithTag:3];
UIImage *btnImage = [UIImage imageNamed:#""];
[imagebutton setImage:btnImage forState:UIControlStateNormal];
[imagebutton setBackgroundColor:[UIColor whiteColor]];
if(headerArray.count>0)
{
if([headerArray containsObject:#"0"])
{
UIImage *btnImage = [UIImage imageNamed:#""];
[imagebutton setImage:btnImage forState:UIControlStateNormal];
[imagebutton setBackgroundColor:[UIColor whiteColor]];
}
else
{
UIImage *btnImage = [UIImage imageNamed:#"ic_floating_done_#1x"];
[imagebutton setImage:btnImage forState:UIControlStateNormal];
[imagebutton setBackgroundColor:[UIColor colorWithRed:0/255.0 green:255/255.0 blue:255/255.0 alpha:1.0]];
}
}
UIButton *btn=(UIButton*)[headerView.contentView viewWithTag:1];
[btn addTarget: self
action: #selector(buttonClicked:)
forControlEvents: UIControlEventTouchUpInside];
return headerView;
}
-(void)buttonClicked:(id)sender
{
if(imagebutton.currentImage == [UIImage imageNamed:#""] )
{
UIImage *btnImage = [UIImage imageNamed:#"ic_floating_done_#1x"];
[imagebutton setImage:btnImage forState:UIControlStateNormal];
[imagebutton setBackgroundColor:[UIColor colorWithRed:0/255.0 green:255/255.0 blue:255/255.0 alpha:1.0]];
}
else
{
UIImage *btnImage = [UIImage imageNamed:#""];
[imagebutton setImage:btnImage forState:UIControlStateNormal];
[imagebutton setBackgroundColor:[UIColor whiteColor]];
}
}
In above My viewForHeader method
My TableviewdidSelect Method
selectedIndex = indexPath.row;
NSNumber *num=[NSNumber numberWithInteger:indexPath.section];
if (!_selectedarray)
{
imagebutton.hidden=YES;
[headerArray addObject:#"0"];
_selectedarray = [[NSMutableArray alloc] init];
}
if(![_selectedarray containsObject:[_rowdata objectAtIndex:selectedIndex]])
{
imagebutton.hidden=NO;
[headerArray removeAllObjects];
[headerArray addObject:#"1"];
[_selectedarray addObject:[_rowdata objectAtIndex:selectedIndex]];
[dataArray addObject:[_rowdata objectAtIndex:selectedIndex]];
[selectedSection addObject:num];
}
else
{
imagebutton.hidden=YES;
[headerArray addObject:#"0"];
[_selectedarray removeObject:[_rowdata objectAtIndex:selectedIndex]];
[dataArray removeObject:[_rowdata objectAtIndex:selectedIndex]];
}
[tableView reloadData];
Im utilizing the "tag" attribute to easily access the Section header in the TableView.
Something like this:
- (void)loadData {
myData = #[
#{
#"Code":#"LB3/7",
#"Name":#"Mixing Bale Opener LB3/7",
#"ParentChildType":#"P",
#"ParentID":[NSNull null],
#"ProductID":#"PRD000004",
#"ProductModelID":#"PMD000001",
#"ChildProductModels":#[
#{
#"Code":#"LB3/7-002",
#"Name":#"With transport apron 4.5 M",
#"ParentChildType":#"C",
#"ParentID":#"PMD000001",
#"ProductID":#"PRD000004",
#"ProductModelID":#"PMD000003"
},
#{
#"Code":#"LB3/7-003",
#"Name":#"With Magnetic Roller",
#"ParentChildType":#"C",
#"ParentID":#"PMD000001",
#"ProductID":#"PRD000004",
#"ProductModelID":#"PMD000004"
}
]
},
#{
#"Code":#"LB7/4",
#"Name":#"UNIMIX MODEL LB7/4",
#"ParentChildType":#"P",
#"ParentID":[NSNull null],
#"ProductID":#"PRD000004",
#"ProductModelID":#"PMD000005",
#"ChildProductModels":#[
#{
#"Code":#"LB7/4-001",
#"Name":#"With Beater",
#"ParentChildType":#"C",
#"ParentID":#"PMD000005",
#"ProductID":#"PRD000004",
#"ProductModelID":#"PMD000006"
}
]
}
];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self loadData];
arrSelectedRows = [NSMutableArray new];
myTableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
myTableView.dataSource = self;
myTableView.delegate = self;
[self.view addSubview: myTableView];
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
NSDictionary *dictParent = [myData objectAtIndex:section];
// Create section header (replace with custom UIView)
UILabel *lblSectionHeader = [UILabel new];
lblSectionHeader.tag = section + 100; // Set tag, so we can access it later
lblSectionHeader.text = [dictParent objectForKey:#"Name"];
return lblSectionHeader;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return myData.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSDictionary *dictParent = [myData objectAtIndex:section];
NSArray *arrChildren = [dictParent objectForKey:#"ChildProductModels"];
return arrChildren.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellId"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"cellId"];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
// Get the parent item
NSDictionary *dictParent = [myData objectAtIndex:indexPath.section];
// Get children
NSArray *arrChildren = [dictParent objectForKey:#"ChildProductModels"];
// Get child row info
NSDictionary *dictItem = [arrChildren objectAtIndex:indexPath.row];
cell.textLabel.text = [dictItem objectForKey:#"Name"];
cell.detailTextLabel.text = [dictItem objectForKey:#"Code"];
// Make sure accessory type is set when the rows are populated
if ([arrSelectedRows containsObject:indexPath]) {
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
} else {
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([arrSelectedRows containsObject:indexPath]) {
// If the selected row was already selected, deselect it
[arrSelectedRows removeObject:indexPath];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[cell setAccessoryType:UITableViewCellAccessoryNone];
// Check if all children are deselected
NSInteger numRowsInSection = [tableView numberOfRowsInSection:indexPath.section];
BOOL areChildrenDeselected = true;
for (NSInteger i = 0; i < numRowsInSection; i++) {
NSIndexPath *childIndexPath = [NSIndexPath indexPathForRow:i inSection:indexPath.section];
if ([arrSelectedRows containsObject:childIndexPath]) {
areChildrenDeselected = false;
}
}
// Get the section header
UILabel *lblSectionHeader = (UILabel *)[tableView viewWithTag: 100 + indexPath.section];
if (areChildrenDeselected) {
lblSectionHeader.textColor = [UIColor blackColor];
} else {
lblSectionHeader.textColor = [UIColor blueColor];
}
} else {
// If the selected row wasnt selected, select it
[tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
[arrSelectedRows addObject:indexPath];
[cell setAccessoryType:UITableViewCellAccessoryCheckmark];
// Get section header
UILabel *lblSectionHeader = (UILabel *)[tableView viewWithTag: 100 + indexPath.section];
lblSectionHeader.textColor = [UIColor blueColor];
}
}
...which results in something like this below, where the parent/section header is automatically set to blue when a child is selected.
To place check marks you can have an UIImageView at the appropriate place for the check mark.
And then you can maintain an array of selected cells, which will contain a boolean, isSelected(or whatever seems good to you).
Then once the user selected a cell, in didSelect delegate method. Just reload you cell by reloadRows:atIndexPath.

Only One RadioButton is Selectable for a Column Group in UITableView

Before asking this question I googled a lot but not able to find suitable answer.
I'm have a UITableView with n number of Columns. The thing is the Column is Grouped according to a key. So my UITableView header is splitted into two, one for the column group and and this column group is divided to show columns.
I have created a custom class for the cell there I display radio button in each column.
Code:
In cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
GridTableViewCell *cell = nil; // My custom class for cell
CGFloat startX = 230;
if (cell == nil)
{
cell = [[GridTableViewCell alloc] initWithStyle1:UITableViewCellStyleDefault reuseIdentifier:#"Cell" withRows:[self.rowHeaderArray objectAtIndex:indexPath.row]];
for (int i = 0; i < [self.groupColumNmeArray count]; i++) { // groupColumNmeArray contains the Column Group name
NSArray *values = [_subColumnDict objectForKey:[self.groupColumNmeArray objectAtIndex:i]]; // subColumnDict contains the value for each column
self.originalDataArray = [CustomTableHeaderParser parseColumnInfo:values];// Parsing the values array for getting column name, type, width etc
for (CustomTableColumn *column in self.originalDataArray)
{
switch (column.columnType) // acc. to column type display the cell with values.
{
case RadioBtn:
{
_btTemp = [[UIButton alloc]initWithFrame:CGRectMake(startX, 2, subCellWidth , 40)];
[_btTemp setTag:indexPath.row];//indexPath.row];
[_btTemp addTarget:self action:#selector(radioButtonsClicked:) forControlEvents:UIControlEventTouchUpInside];
[_btTemp setImage:[UIImage imageNamed:#"radio-off.png"] forState:UIControlStateNormal];
[_btTemp setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
_btTemp.titleLabel.font =[UIFont systemFontOfSize:14.f];
[self.radioButtons addObject:_btTemp];
[cell addSubview:_btTemp];
}
break;
startX += 2+subCellWidth;
}
}
}
cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.frame];
cell.selectedBackgroundView.opaque = YES;
return cell;
}
Radio button click action method;
-(IBAction) radioButtonsClicked:(UIButton *) sender {
if ([sender isSelected]) {
[sender setSelected: NO];
[sender setImage:[UIImage imageNamed:#"radio-off.png"] forState:UIControlStateNormal];
} else {
[sender setSelected: YES];
[sender setImage:[UIImage imageNamed:#"radio-on.png"] forState:UIControlStateNormal];
}
NSLog(#"BUTTON TAG %ld",(long)sender.tag);
}
So I'm able to make selections for radio buttons in all column but actually what I want is For each column group only one radio button is selectable.
Can anybody help me. Any help would be greatly appreciable.
You can set other button's selection status as following
-(IBAction) radioButtonsClicked:(UIButton *) sender {
sender.selected = !sender.selected;
for (UIView *vw in sender.superview.subviews)
{
if([vw isKindOfClass:[UIButton class]] && vw != sender)
{
UIButton *otherBtn = (UIButton*)vw;
otherBtn.selected = NO;
}
}
}
for setting button Image - on/off, write that code at the time of creating button in cellforrow..
[_btTemp setImage:[UIImage imageNamed:#"radio-off.png"] forState:UIControlStateNormal];
[_btTemp setImage:[UIImage imageNamed:#"radio-on.png"] forState:UIControlStateSelected];

Plus and Minus Number in table

I want number of item to add by user like :
-__+
If user add item that he add + button and increase item. so i added textfield to table and add two button Plus(+) and Minus(-). Here is my code in cellForRowAtIndexPath:
if(isPlus){
countFruitQty++;
cell.txtQty.text = [NSString stringWithFormat:#"%i",countFruitQty];
}
else{
countFruitQty--;
if(countFruitQty > 0)
cell.txtQty.text = [NSString stringWithFormat:#"%i",countFruitQty];
else{
cell.txtQty.text = #"";
countFruitQty = 0;
}
But on scroll it change data to all added textField.
How to Prevent this?
You have to manage array for it,
Check below code for your reference, Hope it will help you out
#interface YourViewController ()
{
NSMutableArray *arrMain; // Your main array (Table row count)
NSMutableArray *arrCounter; // Counter array
int a;
}
- (void)viewDidLoad {
arrMain = [[NSMutableArray alloc] init];
arrCounter = [[NSMutableArray alloc] init];
a = 0;
for (int i = 0, i < [arrMain count], i++) {
[arrCounter addObject:[NSString stringWithFormat:#"%d",a]];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
cell.btnPlus.tag = indexPath.row;
[cell.btnPlus addTarget:self action:#selector(click_Plus:) forControlEvents:UIControlEventTouchUpInside];
cell.btnMinus.tag = indexPath.row;
[cell.btnMinus addTarget:self action:#selector(click_Minus:) forControlEvents:UIControlEventTouchUpInside];
cell.txtQty.text = [arrCounter objectAtIndex:indexPath.row];
}
-(IBAction)click_Plus:(UIButton *)sender {
int qnt = [cell.txtQty.text intValue];
cell. txtQty.text = [NSString stringWithFormat:#"%d",++qnt];
[arrCounter replaceObjectAtIndex:sender.tag withObject:cell.txtQty.text];
}
-(IBAction)click_Minus:(UIButton *)sender {
int qnt = [cell.txtQty.text intValue];
cell.txtQty.text = [NSString stringWithFormat:#"%d",--qnt];
[arrCounter replaceObjectAtIndex:sender.tag withObject:cell.txtQty.text];
}
this happens because when you scroll your tableview cell is reused and reset all your textfield
if you want to achieve this functionality you should use scrollview and addSuview when you need

Set button tag for different sections of UITableView

I list of contacts from Web Service and display it in contacts 'sectioned' tableView as seen in the screenshot.
Issue is I get same tag values for checkboxes of first row for section A as well as section S. I have sorted one array and displayed in the indexed table view. How to get different tag values depending on indexPath.row irrespective of number of sections displayed. Here's what I tried
In cellForRowAtIndexPath:
UIButton *checkBox;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
{
checkBox = [[UIButton alloc]initWithFrame:CGRectMake(7, 8, 30, 30)];
}
else
{
checkBox = [[UIButton alloc]initWithFrame:CGRectMake(15, 13, 30, 30)];
}
//int cnt = 0;
// for (int i = indexPath.section - 1; i > 0 ; i--)
// {
// cnt += [[objectsForCharacters objectForKey:[arrayOfCharacters objectAtIndex:i]] count]; //arrayOfCharachters has char 'A' to 'Z'
// }
//checkBox.tag = cnt + indexPath.row;
[checkBox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
[checkBox addTarget:self action:#selector(checkBoxClicked:) forControlEvents:UIControlEventTouchUpInside];
[checkBox setTag:indexPath.row];
[cell.contentView addSubview:checkBox];
return cell;
}
-(void)checkBoxClicked:(id)sender
{
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableViewContact];
NSIndexPath *indexPath = [self.tableViewContact indexPathForRowAtPoint:buttonPosition];
UIButton *tappedButton = (UIButton*)sender;
NSLog(#"Tag number = %d", [sender tag]);
if([tappedButton.currentImage isEqual:[UIImage imageNamed:#"checkBox.png"]])
{
[sender setImage:[UIImage imageNamed: #"checkBoxMarked.png"] forState:UIControlStateNormal];
if(indexPath != Nil)
{
NSString *finalIntId = [mutableArrayOfIds objectAtIndex:indexPath.row]; // store check box ids in mutableArrayOfIds
NSLog(#"Tagged checked button id = %#", finalIntId);
[arrayOfIds addObject:finalIntId];
}
//NSString *finalIntId = [mutableArrayOfIds objectAtIndex:tappedButton.tag];
//NSString *finalIntId = [mutableArrayOfIds objectAtIndex:indexPath.row];
}
else
{
[sender setImage:[UIImage imageNamed:#"checkBox.png"]forState:UIControlStateNormal];
NSLog(#"UnChecked");
//[arrayOfIds removeObjectAtIndex:tappedButton.tag];
}
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if ([arrayOfCharacters count] == 0)
{
return #"";
}
return [NSString stringWithFormat:#"%#", [arrayOfCharacters objectAtIndex:section]];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
NSArray *toBeReturned = [NSArray arrayWithArray:
[#"A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|#"
componentsSeparatedByString:#"|"]];
return toBeReturned;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
NSInteger count = 0;
for (NSString *character in arrayOfCharacters) {
if ([character isEqualToString:title]) {
return count;
}
count ++;
}
return 0;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [arrayOfCharacters count];
//return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//return [mutableArray count];
return [[objectsForCharacters objectForKey:[arrayOfCharacters objectAtIndex:section]] count];
}
you are setting the same tag value for all sections which have same row.
The indexPath has two properties, {section,row}.
Lets say section A has two rows,
for row1 -> indexPath.section=0, indexPath.row=0;
for row2-> indexPath.section=0, indexPath.row=1;
Lets say section S has two rows,
for row1 -> indexPath.section=1, indexPath.row=0;
for row2-> indexPath.section=1, indexPath.row=1;
So, for row1 of section A and row1 of section S, you are setting the same tag value which is 0.There is your problem.
Try setting tag value like below.
button.tag = indexPath.section*1000 +indexPath.row;
when retrieving the section and row,
NSInteger section = (button.tag)/1000;
NSInteger row = (button.tag)%1000;
Try this...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
UIButton *checkBox =[[UIButton alloc] initWithFrame:CGRectMake(280, 10, 50, 44)];
checkBox.backgroundColor =[UIColor orangeColor];
[checkBox addTarget:self action:#selector(checkBoxClicked:event:)forControlEvents:UIControlEventTouchUpInside];
[checkBox setTag:indexPath.row];
[cell.contentView addSubview:checkBox];
return cell;
}
- (void)checkBoxClicked:(id)sender event:(id)event
{
NSSet *touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentTouchPosition = [touch locationInView:self.tv]; //here tv is TableView Object
NSIndexPath *indexPath = [self.tv indexPathForRowAtPoint: currentTouchPosition];
NSLog(#"value of indePath.section %d ,indexPath.row %d",indexPath.section,indexPath.row);
}
This is happening because you are assigning tag to buttons INDEPENDENT of sections.
Both of First Row of Sections A & S have row = 0. so Tag Assigned to their respective button is 0. You should assign them Keeping reference to your sections.
i would suggest to assign accessibility hint with comma separated form containing Section,Row.
And in your method
-(void)checkBoxClicked:(id)sender
{
//pick string from comma separated form. 1st is your section, 2nd is row.
}
second option is Do what ever your doing and implement your Button method like this.
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
if (indexPath != nil)
{
... indexpath.section is your section , index path.row is your row.
}
There is Third option as well.
in cellforRowAtIndexpath assign your Button a title
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
[btn setTitle:<#Your Row#> forState:UIControlStateDisabled];
[btn setTag<#Your Section#>];
so upon Receiving in your Button Method you can have both Section (Tag) and Row (Title for Disabled state).
-(void)checkBoxClicked:(id)sender { [button titleForState:UIControlStateDisabled]; // your Row
button.tag //your Section }
Try this!
Each section you may know the count of section right, then add count of individual row.
[[fieldTitlesList objectAtIndex:indexPath.section - 1] count] + indexPath.row
Where fieldTitlesList is the array of your sections.
I added the following code which solved my issue
NSInteger rowNumber = 0;
for(NSInteger i = 0; i < indexPath.section ; i++)
{
rowNumber += [self tableView:self.tableViewContact numberOfRowsInSection:i];
}
rowNumber += indexPath.row;
[checkBox setTag:rowNumber]; //checkBox is UIButton in cellForRowAtIndexPath

Button Image Quality Collection View

I have a collection view where each cell contains 7 buttons, (created via code not storyboard).
They are sharp initially, however if I scroll up / down a few times the quality decreases.
The sharpness is restored when I change views and return.
Any ideas ?
Addit:
I am making the buttons like this, within a loop (can be 1 to 7 buttons)
- (UICollectionViewCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"patientCell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
Patient *aPt = [self.fetchedResultsController objectAtIndexPath:indexPath];
PatientCVCell *ptCell = (PatientCVCell *) cell;
ptCell.ptName.text = aPt.name;
ptCell.ptRoom.text = aPt.room;
ptCell.ptRx.text = aPt.diagnosis;
int xPos = 20;
NSArray *daysForRx = aPt.ofList.listDays;
// loop through to add button for each day of Rx
for (int i = 0; i < [daysForRx count]; i++) {
// get the treatment day that == postition in array
for (Treatment *t in aPt.patientRx) {
if (t.day == daysForRx[i]) {
//NSLog(#"%i", xPos);
StatusButton *testButton = [StatusButton buttonWithType:UIButtonTypeCustom];
testButton.frame = CGRectMake(xPos, 110, 28, 28);
testButton.btnTreatment = t;
// match status of the RX to the correct button
if ([t.status intValue] == NotSeen) {
[testButton setImage:[UIImage imageNamed:#"toSee"] forState:UIControlStateNormal];
testButton.linkNumber = NotSeen;
}
else if ([t.status intValue] == SeenNotCharted) {
[testButton setImage:[UIImage imageNamed:#"seenNotCharted"] forState:UIControlStateNormal];
testButton.linkNumber = SeenNotCharted;
}
else if ([t.status intValue] == SeenCharted) {
[testButton setImage:[UIImage imageNamed:#"seenCharted"] forState:UIControlStateNormal];
testButton.linkNumber = SeenCharted;
}
else if ([t.status intValue] == NotSeeing) {
[testButton setImage:[UIImage imageNamed:#"notSeeing"] forState:UIControlStateNormal];
testButton.linkNumber = NotSeeing;
}
else if ([t.status intValue] == NotSeeingDC) {
[testButton setImage:[UIImage imageNamed:#"notSeeingDischarged"] forState:UIControlStateNormal];
testButton.linkNumber = NotSeeingDC;
}
[testButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:testButton];
xPos = xPos + 36;
}
}
}
return cell;
}
The image is correct size so no need to scale the image.
Occurs in simulator and on device.
After looking more closely, the inside of the images are sharp! So this issue has to do with the transparency for my circle shape of a button within a square button!
You are dequeuing a cell, then you add your buttons to the dequeued cell.
Those buttons never get removed. When you scroll up and down cells that go off screen are put on the dequeue queue. At this time they still have the buttons, then they are dequeued and you add more buttons. You have many buttons above each other, and that's why it looks blurry and your memory footprint gets bigger.
I would add the buttons from inside the cell. Save them in a array so you can remove them later. Then I would add a method to set the number of buttons you'll need. Like this:
// header
#property (strong, nonatomic) NSMutableArray *buttons;
// implementation
- (void)setNumberOfButtons:(NSInteger)numberOfButtons withTarget:(id)target selector:(SEL)selector {
// remove existing buttons from view
[self.buttons makeObjectsPerformSelector:#selector(removeFromSuperview)];
// "save" existing buttons in a reuse queue so you don't have to alloc init them again
NSMutableArray *reuseQueue = self.buttons;
self.buttons = [NSMutableArray arrayWithCapacity:numberOfButtons];
for (NSInteger i = 0; i < numberOfButtons; i++) {
UIButton *button = [reuseQueue lastObject];
if (button) {
[reuseQueue removeLastObject];
}
else {
button = [UIButton buttonWithType:UIButtonTypeCustom];
// you should always use the same target and selector for all your cells. otherwise this won't work.
[button addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];
}
[self.buttons addObject:button];
button.frame = ....
// don't set up images or titles. you'll do this from the collectionView dataSource method
}
}
you would then set the number of buttons in collectionView:cellForItemAtIndexPath: and configure each button according to your needs. something along those lines:
- (UICollectionViewCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
Cell *cell = ... dequeue ...
Object *object = ... get from your backend ...
/* configure your cell */
if ([cell.buttons count] != object.numberOfItems) {
// no need to remove and add buttons if the item count stays the same
[cell setNumberOfButtons:object.numberOfItems withTarget:self selector:#selector(buttonPressed:)];
}
for (NSInteger i = 0; i < [object.numberOfItems count]; i++) {
UIButton *button = cell.buttons[i];
[button setImage:... forState:UIControlStateNormal];
}
}
And the action would look like this:
- (IBAction)buttonPressed:(UIButton *)sender {
UICollectionView *collectionView;
CGPoint buttonOriginInCollectionView = [sender convertPoint:CGPointZero toView:collectionView];
NSIndexPath *indexPath = [collectionView indexPathForItemAtPoint:buttonOriginInCollectionView];
NSAssert(indexPath, #"can't calculate indexPath");
Cell *cell = [collectionView cellForItemAtIndexPath:indexPath];
if (cell) {
NSInteger pressedButtonIndex = [cell.buttons indexOfObject:sender];
if (pressedButtonIndex != NSNotFound) {
// do something
}
}
else {
// cell is offscreen?! why?
}
}
pretty straight forward. Get the indexPath, get the collectionViewCell, check which index the pressed button has

Resources