I have created two custom cells with UILabel and UIImageView.
Even if I added space between them the UIImageView cell overlaps with the UILabel cell. In addition, I am updating the frame of the UIlabel cell but its not updating. I am not using autolayout. Can any one give me solution for this?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
DetermineCoatingCell *cell=[[NSBundle mainBundle] loadNibNamed:#"DetermineCoatingCell" owner:self options:nil][0];
float cellHeight = [self tableView:tableView heightForRowAtIndexPath:indexPath];
NSDictionary *option =[arrOptions objectAtIndex:indexPath.row];
if (is_iPad) {
// float yValue=(cellHeight/2)-10;
lblTable= [[UILabel alloc]initWithFrame:CGRectMake(30, 5, 590, cellHeight)];
lblTable.font=[UIFont systemFontOfSize:30];
lblTable.numberOfLines=0;
lblTable.textColor=[UIColor colorWithRed:63.0/255.0f green:126.0/255.0f blue:199.0/255.0f alpha:1.0];
lblTable.textAlignment=NSTextAlignmentLeft;
} else {
// float yValue=(cellHeight/2)-5;
if (![option[#"CoatingImage"] isEqualToString:#""]) {
cell.imgView.tag = indexPath.row;
cell.imgView.userInteractionEnabled = YES;
UITapGestureRecognizer *tapgesture=[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imgViewTapped:)];
tapgesture.numberOfTapsRequired = 1;
tapgesture.view.tag = indexPath.row;
tapgesture.cancelsTouchesInView = NO;
// [tapgesture setValue:[NSString stringWithFormat:#"%ld",indexPath.row] forKey:#"Tag"];
[cell.imgView addGestureRecognizer:tapgesture];
NSString *key = [[option valueForKey:#"CoatingImage"] MD5Hash];
NSData *data = [FTWCache objectForKey:key];
if (data) {
UIImage *image = [UIImage imageWithData:data];
cell.imageView.image=image;
} else {
[WebImageOperations processImageDataWithURLString:[option valueForKey:#"CoatingImage"] andBlock:^(NSData *imageData) {
[FTWCache setObject:imageData forKey:key];
UIImage *image = [UIImage imageWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image=image;
});
}];
}
} else {
CGRect framelbl = CGRectMake(0,0, cell.lblTitle.frame.size.width,cell.lblTitle.frame.size.height);
NSLog(#"%#",NSStringFromCGRect(framelbl));
[cell.lblTitle setFrame:framelbl];
}
}
cell.lblTitle.text=[NSString stringWithFormat:#"%#",[option valueForKey:#"AnswerOptionText" ]];
cell.lblTitle.textColor=[UIColor colorWithRed:63.0/255.0f green:126.0/255.0f blue:199.0/255.0f alpha:1.0];
NSLog(#"lblTableText %#",lblTable.text);
if(selectedPath.row == indexPath.row && selectedPath.section == indexPath.section)
{
cell.backgroundColor = [UIColor colorWithRed:227.0/255.0f green:227.0/255.0f blue:227.0/255.0f alpha:1.0];;
} else {
cell.backgroundColor = [UIColor clearColor];
}
return cell;
}
If you're determined not to use autolayout in the table view, then investigate the table view delegate method -[id tableView:heightForRowAtIndexPath:]:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewDelegate_Protocol/#//apple_ref/occ/intfm/UITableViewDelegate/tableView:heightForRowAtIndexPath:
You'll need to identify which row corresponds to an image view cell, and which to a label cell, and then return the appropriate height.
Related
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.
When I'm trying to pass the value of a NSString made up of a single word from a cell with the minimum font scale or size set, it seem to work checking with NSLogs, but when I'm trying to compare it with another string it gives me a [NSNull length] unrecognised selector sent etc. With string composed by more words it works fine. I think it's a bug of Xcode 7. Has anyone else experience that? Is there a work around?
I tried setting the label on the cell both programmatically and on Interfece Builder, with the same result. My custom tableview cell is the following
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"aCell"];
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:#"aCell" forIndexPath:indexPath];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.contentView.backgroundColor = [UIColor colorWithRed:165.0/255.0 green:15.0/255.0 blue:2.0/255.0 alpha:1];
cell.textLabel.backgroundColor = [UIColor colorWithRed:165.0/255.0 green:15.0/255.0 blue:2.0/255.0 alpha:1];
cell.textLabel.textAlignment = NSTextAlignmentCenter;
cell.textLabel.font = [UIFont fontWithName:#"AvenirNext-Medium" size:22.0f];
cell.textLabel.textColor = [UIColor colorWithRed:243.0/255.0 green:243.0/255.0 blue:243.0/255.0 alpha:1];
UIView * separatorLineView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, cell.frame.size.width, 2)];
separatorLineView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"QastItBackground"]];
[cell.contentView addSubview:separatorLineView];
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.textLabel.minimumScaleFactor = 0.5;
NSDictionary *categories = [Options categories];
NSArray *details = [categories objectForKey:self.title];
NSString *detail = details [indexPath.row];
cell.textLabel.text = detail;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [[self tableView] cellForRowAtIndexPath:indexPath];
NSString *selection = cell.textLabel.text;
[[TemporarySelection sharedStore]updateSelection:selection];
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:#"Storyboard" bundle:nil];
if ([self.title isEqualToString:#"Two Ways"]) {
TwoWaysViewController *twvc = [[TwoWaysViewController alloc]init];
twvc = (TwoWaysViewController *)[storyboard instantiateViewControllerWithIdentifier:#"TwoWays"];
[self presentViewController:twvc animated:YES completion:nil];
CFRunLoopWakeUp(CFRunLoopGetCurrent());
} else {
DieFacesViewController *dfvc = (DieFacesViewController *)[storyboard instantiateViewControllerWithIdentifier:#"DieFaces"];
[self presentViewController:dfvc animated:YES completion:nil];
CFRunLoopWakeUp(CFRunLoopGetCurrent());
}
}
then in the new view controller I take the value from the singleton and I compare it with another string
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
NSString *ts = [[TemporarySelection sharedStore]temporarySelection];
NSArray *favourites = [[FavouritesStore sharedStore]allFavourites];
NSArray *selectedFaces = [[SelectedStore sharedStore]selectedOptions];
UIGraphicsBeginImageContext(self.view.frame.size);
[[UIImage imageNamed:#"selectorbg"] drawInRect:self.view.bounds];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.view.backgroundColor = [UIColor colorWithPatternImage:image];
self.selectionName.text = ts;
NSLog(#"%#", ts);
NSLog(#"%#", selectedFaces[0] );
if ([self.selectionName.description isEqualToString: selectedFaces[0]]) {
self.faceOne.image = [UIImage imageNamed:#"face1red"];
} else if (selectedFaces[0] == [NSNull null]) {
self.faceOne.image = [UIImage imageNamed:#"face1white"];
} else {
self.faceOne.image = [UIImage imageNamed:#"face1grey"];
}
}
the NSLog show the correct string and with the breakpoint everything is smooth till the first if statement. if I remove it the second statement is fine, so the problem has to lie on the *ts NSString.
I have another tableview with a custom class cell via interface builder and it has the same problem. I know it can sound very confusing, but I tried everything I can think of and that seem to be the cause.
I have a custom table view cell with slider and a label. I have created a property for the slider and label on my custom cell. I want to transfer the slider value to the label. This is what I tied:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *cellInfo = [[self.sections objectAtIndex:currentTab] objectAtIndex:indexPath.row];
HLMagnitudoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[cellInfo objectForKey:#"cell"] forIndexPath:indexPath];
UIImageView *radioIndicator = (UIImageView *)[cell.contentView viewWithTag:200];
radioIndicator.image = (currentBullet != indexPath.row) ? [UIImage imageNamed:#"RadioOff"] : [UIImage imageNamed:#"RadioOn"];
UIImageView *av = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 80)];
av.backgroundColor = [UIColor clearColor];
av.opaque = NO;
av.image = [UIImage imageNamed:#"NewsSeparetor.png"];
cell.backgroundView = av;
cell.slider.maximumValue = 100;
cell.slider.minimumValue = 1;
cell.slider.continuous = TRUE;
cell.slider.tag = 1;
cell.slider.value = [cell.label.text intValue];
[cell.slider addTarget:self action:#selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];
return cell;
}
- (void)sliderChanged:(UISlider *)slider
{
}
Create your sliders in the cells and set a tag value for each one:
eg:
slider.tag=1
The register a method to be called when the value is updated:
[slider addTarget:self action:#selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];
Then in your method you will be able to get the values for sliders using the tag:
-(void)sliderChanged:(UISlider *)sender {
int tag = sender.tag;
if (tag ==1 ) //Update the label
slider1Label.text=[NSString strinWithFormat:#"%d",sender.value]
}
else if (tag == 2){
//Do something else
}
}
If i select some segments and then scroll the tableView down, it forgets my selected segments?
What am I do'ing wrong? Or what am I missing? It looks like it resets the cell every time, but I've tried to remove the cell = nil; but with no luck. All the code I think might have impact on this is here:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"FancyCell"];
cell = nil;
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"FancyCell"];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
// add the segmentedControl when you create a new cell
UIImage *correctImageGreen = [[UIImage imageNamed:#"green.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIImage *correctImageGul = [[UIImage imageNamed:#"gul.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIImage *correctImageRed = [[UIImage imageNamed:#"red.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
NSArray *itemArray = [NSArray arrayWithObjects: correctImageGreen, correctImageGul, correctImageRed, nil];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:itemArray];
segmentedControl.frame = CGRectMake(308, 8, 150, 28);
[cell.contentView addSubview:segmentedControl];
// add an action so we can change our model if the view changes
[segmentedControl addTarget:self action:#selector(didChangeSegmentedControl:) forControlEvents:UIControlEventValueChanged];
// use a tag so we can retrieve the segmentedControl later
segmentedControl.tag = 42;
}
// either if the cell could be dequeued or you created a new cell,
// segmentedControl will contain a valid instance
UISegmentedControl *segmentedControl = (UISegmentedControl *)[cell.contentView viewWithTag:42];
UIImage *comment = [UIImage imageNamed:#"Checkmark-hvid"];
UIImage *imageRef = [UIImage imageNamed:#"Checkmark-hvid"];
UIImageView *commentView = [[UIImageView alloc] initWithImage: comment];
UIImageView *imageRefView = [[UIImageView alloc] initWithImage: imageRef];
commentView.frame = CGRectMake(625, 5, 30, 30);
imageRefView.frame = CGRectMake(515, 5, 30, 30);
commentView.tag = 98;
imageRefView.tag = 99;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
boolean_t didGetStates = [defaults boolForKey:#"didGetStates"];
if (didGetStates) {
NSDictionary *dic = [tableData objectAtIndex:indexPath.row];
int selectedState = [[dic valueForKey:#"State"] intValue];
[cell.contentView addSubview:segmentedControl];
if (selectedState == -1) {
segmentedControl.selectedSegmentIndex = -1;
}
else {
segmentedControl.selectedSegmentIndex = selectedState;
}
int comment = [[dic valueForKey:#"Comment"] intValue];
int imageRef = [[dic valueForKey:#"Foto"] intValue];
if (comment == 0) {
[cell.contentView addSubview:commentView];
}
else {
[[cell.contentView viewWithTag:98]removeFromSuperview];
}
if (imageRef == 0) {
[cell.contentView addSubview:imageRefView];
}
else {
[[cell.contentView viewWithTag:99]removeFromSuperview];
}
}
MBFancyObject *object = _objects[indexPath.row];
cell.textLabel.text = object.title;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
object.selectedIndex = segmentedControl.selectedSegmentIndex;
object.currentIndexRow = indexPath.row;
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.textColor = [UIColor whiteColor];
return cell;
}
The action that is called, when a segment is chosen..
- (IBAction)didChangeSegmentedControl:(UISegmentedControl *)sender {
// transform the origin of the cell to the frame of the tableView
CGPoint senderOriginInTableView = [self.tableView convertPoint:CGPointZero fromView:sender];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:senderOriginInTableView];
NSAssert(indexPath, #"must have a valid indexPath");
MBFancyObject *object = _objects[indexPath.row];
object.selectedIndex = sender.selectedSegmentIndex;
}
If you got any idea please write an answer or if you need more information tell me!! :)
THANK YOU!!!
Mikkel - The 15 year old iDeveloper! ;)
You are misunderstanding how table view cells work. They are not for saving state information, they are for presenting it, and interacting with the user.
When a table view cell is scrolled off-screen, the system tosses it into a recycle queue, and any field settings in the cell are lost.
When a user interacts with the controls in your table view, you should immediately save the changed information to your model (data storage). Then, when the table view asks you for a cell in the tableView:cellForRowAtIndexPath: method, you should create and FULLY configure a cell with the values from your model.
I found out that i forgot that i get data from my database, witch returns -1. And if I choose segment 2 and then scroll down and then back up, it show the value from the database :) This was fixable by adding a boolan to check where it should look fore the selected segment :) Now it looks like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"FancyCell"];
cell = nil;
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"FancyCell"];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
// add the segmentedControl when you create a new cell
UIImage *correctImageGreen = [[UIImage imageNamed:#"green.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIImage *correctImageGul = [[UIImage imageNamed:#"gul.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIImage *correctImageRed = [[UIImage imageNamed:#"red.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
NSArray *itemArray = [NSArray arrayWithObjects: correctImageGreen, correctImageGul, correctImageRed, nil];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:itemArray];
segmentedControl.frame = CGRectMake(308, 8, 150, 28);
[cell.contentView addSubview:segmentedControl];
// add an action so we can change our model if the view changes
[segmentedControl addTarget:self action:#selector(didChangeSegmentedControl:) forControlEvents:UIControlEventValueChanged];
// use a tag so we can retrieve the segmentedControl later
segmentedControl.tag = 42;
}
// either if the cell could be dequeued or you created a new cell,
// segmentedControl will contain a valid instance
UISegmentedControl *segmentedControl = (UISegmentedControl *)[cell.contentView viewWithTag:42];
UIImage *comment = [UIImage imageNamed:#"Checkmark-hvid"];
UIImage *imageRef = [UIImage imageNamed:#"Checkmark-hvid"];
UIImageView *commentView = [[UIImageView alloc] initWithImage: comment];
UIImageView *imageRefView = [[UIImageView alloc] initWithImage: imageRef];
commentView.frame = CGRectMake(625, 5, 30, 30);
imageRefView.frame = CGRectMake(515, 5, 30, 30);
commentView.tag = 98;
imageRefView.tag = 99;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
boolean_t didGetStates = [defaults boolForKey:#"didGetStates"];
boolean_t didSelectState = [defaults boolForKey:#"didSelectState"];
MBFancyObject *object = _objects[indexPath.row];
if (didGetStates) {
NSDictionary *dic = [tableData objectAtIndex:indexPath.row];
if (didSelectState) {
segmentedControl.selectedSegmentIndex = object.selectedIndex;
}
else {
int selectedState = [[dic valueForKey:#"State"] intValue];
[cell.contentView addSubview:segmentedControl];
if (selectedState == -1) {
segmentedControl.selectedSegmentIndex = -1;
}
else {
segmentedControl.selectedSegmentIndex = selectedState;
}
}
int comment = [[dic valueForKey:#"Comment"] intValue];
int imageRef = [[dic valueForKey:#"Foto"] intValue];
if (comment == 0) {
[cell.contentView addSubview:commentView];
}
else {
[[cell.contentView viewWithTag:98]removeFromSuperview];
}
if (imageRef == 0) {
[cell.contentView addSubview:imageRefView];
}
else {
[[cell.contentView viewWithTag:99]removeFromSuperview];
}
}
cell.textLabel.text = object.title;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
object.selectedIndex = segmentedControl.selectedSegmentIndex;
object.currentIndexRow = indexPath.row;
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.textColor = [UIColor whiteColor];
return cell;
}
And the segmentedControl's action:
- (IBAction)didChangeSegmentedControl:(UISegmentedControl *)sender {
// transform the origin of the cell to the frame of the tableView
CGPoint senderOriginInTableView = [self.tableView convertPoint:CGPointZero fromView:sender];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:senderOriginInTableView];
NSAssert(indexPath, #"must have a valid indexPath");
MBFancyObject *object = _objects[indexPath.row];
object.selectedIndex = sender.selectedSegmentIndex;
[[NSUserDefaults standardUserDefaults] setBool:TRUE forKey:#"didSelectState"];
}
I have a UITable that reuses cells. Each cell has an image dependant on a condition. The correct images are always used however when cells are reused the old image is displayed behind the new one. I have tried to remove the uiimageview before adding a new subview however it has no effect.
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
UIImageView *achievImg = [[UIImageView alloc] init];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
[achievImg removeFromSuperview];
[cell.contentView addSubview:achievImg];
return cell;
}
Any help would be greatly appreciated?
The problem is each time cellForRowAtIndexPath: is called you create a new imageview.
I corrected your code as follows:
Here we create an imageView once for each new new cell and replace it's image every time cellForRowAtIndexPath: is called:
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
UIImageView *achievImg = nil;
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
//New Cell ... Create Image view
achievImg = [[UIImageView alloc] init];
achievImg.tag = 10;
[cell.contentView addSubview:achievImg];
}
else{
//Old cell...get previously createdd imageview
achievImg = (UIImageView*)[cell.contentView viewWithTag:10];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
//You don't need this because it doesn't have a superview in the first place..it's new
//[achievImg removeFromSuperview];
return cell;
}
try like this,
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpTableIden = #"simpTableIden";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpTableIden];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpTableIden];
NSUInteger row = [indexPath row];
cell.textLabel.text = [[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"name"];
CGRect picFrame = CGRectMake(cell.frame.size.width-cell.frame.size.height, 0, cell.frame.size.height, cell.frame.size.height);
UIImage *greyDot = [UIImage imageNamed:#"greyDot.png"];
UIImage *whiteDot = [UIImage imageNamed:#"whiteDot.png"];
UIImageView *achievImg = [[UIImageView alloc] init];
tableView.backgroundColor = [UIColor clearColor];
achievImg.frame=picFrame;
if ([[[self.achievements objectForKey:[keys objectAtIndex:row]] objectForKey:#"achieved"] boolValue]) {
achievImg.image = whiteDot;
}
else {
achievImg.image = greyDot;
}
[achievImg removeFromSuperview];
[cell.contentView addSubview:achievImg];
}
return cell;
}
You are always adding the imageView to the contentView of the cell. If the cell is reused that will lead to multiple imageViews in cell.
You can give a tag to the imageView. Always check if there is a view will same tag in the contentView of cell. If not add the imageView.
UIImageView *achievImg = (UIImageView *)[cell.contentView viewWithTag:55];
if(!achievImg){
achievImg = [[UIImageView alloc] init];
achievImg.tag = 55;
[cell.contentView addSubView:achievImg];
}