Make TableView buttons take up less memory - ios

I have code here that generates a list of cells that contain buttons.
I'm pretty sure there is a way to make it so that I am creating 1 button object instead of 20, but I'm not quite sure how to implement that?
I need some guidance as to where to make it so I only create 1 button object.
Additionally, I might be making 20 cell objects when I only need 1 as well?
I don't totally understand how to utilize memory well yet.
My code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = #"TimesCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
//[cell sizeToFit];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if([cell.contentView viewWithTag:3] != nil){
[[cell.contentView viewWithTag:3] removeFromSuperview];
}
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(customActionPressed:)
forControlEvents:UIControlEventTouchDown];
[button setTitleEdgeInsets:UIEdgeInsetsMake(-10.0f, 0.0f, 0.0f, 0.0f)];
button.frame = CGRectMake(5, 5, 310, 50);
button.tag = 3;
int rows = [yourDefaultActivities count];
int rowsl = rows - 1;
float r = 1+(((255-1+75)/rowsl)*(indexPath.row));
if(r > 255){
r = 255;
}
float g = 255-(((255-1+75)/rowsl)*(indexPath.row));
if(g < 0){
g = 255-fabsf(g);
}else{
g = 255;
}
float b = 1;
UIColor *thisColor = [UIColor colorWithRed:r/255 green:g/255 blue:b/255 alpha:1];
button.backgroundColor = thisColor;
button.clipsToBounds = YES;
button.layer.cornerRadius = 15;
button.titleLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:14];
[button setTitle:[[yourDefaultActivities objectAtIndex:indexPath.row] objectAtIndex:0] forState:UIControlStateNormal];
[button.titleLabel setTextColor:[UIColor blackColor]];
[button.titleLabel setFont:[UIFont fontWithName:#"HelveticaNeue" size:14]];
[cell addSubview:button];
return cell;
}
EDIT: I tried to remove the buttons every time I created a new one, but I must be doing it wrong..

One button object can't appear in 8 cells at once -- you do need as many cells and buttons as will fit on the screen at any time (it looks like 8 or 9). But 8 or 9 cell with buttons in them should not cause any memory problems -- buttons aren't that expensive. The problem with the code you posted though, is that it is adding buttons every time cellForRowAtIndexPath is called, which happens a lot when you scroll. Since cells are reused, you don't want to be adding a button to a cell that already has one. The easiest solution, in my opinion, is to make a custom cell in the storyboard, and add you buttons there. You can still set their color in code based on the indexPath so you get the look you want. Alternately, you can check whether the cell (actually the cell.contentView which is where you should be adding them, not directly to the cell) has a subview of class UIButton, and only add a button if it doesn't already have one.
After Edit:
In answer to your comment, you don't need to make the rounded button in the storyboard, you can just add a button (type custom) to your subclassed cell, and then modify its look in code. Here is an example of what I mean. In this test app, I created a custom cell class (RDCell) and changed the class of the cell in the storyboard to that. I added a custom button to the cell, positioned and sized it with constraints, and made an IBOutlet to it in RDCell.h. Here is what I have in the table view controller:
#import "TableController.h"
#import "RDCell.h"
#implementation TableController
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(RDCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.button.backgroundColor = [UIColor colorWithHue:.15 + (indexPath.row/30.0) saturation:1 brightness:1 alpha:1];
cell.button.layer.cornerRadius = 15;
cell.button.titleLabel.textColor = [UIColor blackColor];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RDCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
[cell.button addTarget:self action:#selector(customActionPressed:) forControlEvents:UIControlEventTouchUpInside];
cell.button.tag = indexPath.row;
return cell;
}
-(void)customActionPressed:(UIButton *) sender {
NSLog(#"button pressed in row: %d",sender.tag);
[self.tableView reloadRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:sender.tag inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
}
This was the resultant view:
I put a log in initWithCoder for RDCell, and it's called only 12 times (the max. number of cells on the screen at any one time), so there's never more than 12 cells or 12 buttons.

Related

UITableViewCell - can't get UIButton subview to overlap (and be tappable in) next cell in iOS 9

I am trying to add a UIButton subview to a UITableViewCell and have it overlap onto the cell below. Specifically, I want my implementation to look like the Edit Contact view in iOS Contacts, with the Contact photo (button) to the left and the first and last name to the right.
This used to work in iOS 7, and I am pretty certain it also worked in iOS 8. I have tried literally everything I can think of to get this to work in iOS 9. I can get the button to overlap into the next cell, but it is not tappable. No matter what, when I click on the bottom half of the button (the half that is in the overlap part of the second cell), the button is not recognized (nothing happens). Here are all of the things that I have tried, unsuccessfully.
When I created the tableView I set
tableView.clipsToBounds = NO;
And
- (void)tableView:(UITableView *)tableView1 willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.section) {
case CONTACT_EDIT_SECTION: {
switch (indexPath.row) {
case NAME_FIRST_ROW: case NAME_LAST_ROW:
[cell setClipsToBounds:NO];
[cell.contentView setClipsToBounds:NO];
[cell.contentView.superview setClipsToBounds:NO];
[cell.contentView.superview.superview setClipsToBounds:NO];
}
break;
}
}
break;
}
}
I read that when a tableView is in editing mode, the cells get set back to cell.contentView.clipsToBounds = YES. So
- (void)setEditing:(BOOL)editing {
[super setEditing:editing];
UITableView *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:NAME_FIRST_ROW inSection:CONTACT_EDIT_SECTION]];
cell.contentView.clipsToBounds = NO;
UITableView *cell2 = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:NAME_LAST_ROW inSection:CONTACT_EDIT_SECTION]];
cell2.contentView.clipsToBounds = NO;
}
Obviously, I tried setting clipsToBounds No in the cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath {
__ENTERING_METHOD__
switch (indexPath.section) {
case CONTACT_EDIT_SECTION: {
switch (indexPath.row) {
case NAME_FIRST_ROW: case NAME_LAST_ROW: {
UITableViewCell *cell;
if (indexPath.row == 0) {
cell = [tableView1 dequeueReusableCellWithIdentifier:#"Value1Cell" forIndexPath:indexPath];
UIButton *imageButton = [[UIButton alloc] initWithFrame:CGRectMake(LEFT_CELL_MARGIN, (2*DEFAULT_ROW_HEIGHT-IMAGE_DIAMETER)/2.0, IMAGE_DIAMETER, IMAGE_DIAMETER)];
[imageButton setBackgroundColor:[UIColor redColor]];
//[imageButton.layer setMasksToBounds:YES];
[imageButton.layer setCornerRadius:IMAGE_DIAMETER/2.0];
[imageButton.layer setBorderWidth:1];
[imageButton.layer setBorderColor:[UIColor colorWithRed:200 green:200 blue:200 alpha:1].CGColor];
[imageButton setImage:_person.thumbnailImage forState:UIControlStateNormal];
[imageButton addTarget:self action:#selector(photoActionSheet:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView.superview addSubview:imageButton];
[cell setClipsToBounds:NO];
[cell.contentView setClipsToBounds:NO];
[cell.contentView.superview setClipsToBounds:NO];
[cell.contentView.superview.superview setClipsToBounds:NO];
}
else {
cell = [tableView1 dequeueReusableCellWithIdentifier:#"Value1Cell" forIndexPath:indexPath];
[cell setClipsToBounds:NO];
[cell.contentView setClipsToBounds:NO];
[cell.contentView.superview setClipsToBounds:NO];
[cell.contentView.superview.superview setClipsToBounds:NO];
}
[cell layoutIfNeeded];
return cell;
}
break;
}
}
break;
}
return nil;
}
Usually after googling for four hours and trying everything I can possibly find, I can solve a problem like this. Help would be greatly appreciated.
You need to create a cell with the multiple text fields and the portrait image in it. Overlapping from an external cell is very tetchy as the view order can be altered by the user scrolling cells in and out.
You can confirm this in the contacts app, when you select a phone number cell or anything below, it will highlight the cell, however when tapping the first/last/company cells, it doesn't do the highlight. This is because that is once cell in itself.

UITableView Not Smooth Scrolling during dynamic cell contents change based on the settings

I have a Table View that rows data display basis on the user settings.
Like I have check box for Task, Start Date, Priority , Process, State , Description Etc.
I user check Task and Description then I create UITableViewCell then Add Label for Task And Description if user check All the Settings then Cell should Display all the Label created.
What Problem I am facing is that UITableView Not Scrolling smoothly its not reusing the cell when user scrolls it second Time after Loading the settings.
Below is the code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellMainNibID = #"cellMain";
NSUInteger count=[arrSettings count];
TaskItem* item=[self.arrTaskList objectAtIndex:indexPath.row];
CGFloat y=2;
UITableViewCell* cell=(UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:cellMainNibID];
if (_cellMain == nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellMainNibID];
for (int i=0; i<count; i++)
{
UILabel *lbll=(UILabel*)[cell.contentView viewWithTag:indexPath.row+ i+200];
NSLog(#" cell label = %#",lbll); //**Return null always**
UILabel* lbl=[[UILabel alloc]initWithFrame:CGRectMake(10, y, 310, 14)];
lbl.tag=indexPath.row+ i+200;
lbl.backgroundColor=[UIColor clearColor];
lbl.textColor=[UIColor whiteColor];
lbl.font=[UIFont boldSystemFontOfSize:14];
[cell.contentView addSubview:lbl];
lbl=nil;
NSString* str=[arrSettings objectAtIndex:i];
CGRect rect;
if ([str isEqualToString:#"description"])
rect=CGRectMake(8, y+14, 290, 50);
else
rect=CGRectMake(110, y, 290, 14);
UILabel *lblll=(UILabel*)[cell.contentView viewWithTag:indexPath.row+ i+400];
NSLog(#" cell label = %#",lblll); //**Return null always**
UILabel* lbl2=[[UILabel alloc]initWithFrame:rect];
lbl2.backgroundColor=[UIColor clearColor];
lbl2.tag=indexPath.row+i+400;
lbl2.textColor=[UIColor whiteColor];
lbl2.font=[UIFont systemFontOfSize:14];
lbl2.numberOfLines=5;
lbl2.lineBreakMode=NSLineBreakByCharWrapping;
[cell.contentView addSubview:lbl2];
y+=lbl2.frame.size.height+1;
lbl2=nil;
}
}
for (int i=0; i<count; i++)
{
UILabel* lbl=(UILabel*)[cell.contentView viewWithTag:indexPath.row+i+200];
lbl.text=[[[arrSettings objectAtIndex:i]uppercaseString]stringByAppendingString:#":"];
UILabel* lbl2=(UILabel*)[cell.contentView viewWithTag:indexPath.row+i+400];
lbl2.text=[item valueForKey:[arrSettings objectAtIndex:i]];
}
cell.contentView.backgroundColor=[UIColor clearColor];
cell.backgroundColor=[UIColor clearColor];
_cellMain.contentView.backgroundColor=[UIColor clearColor];
_cellMain.backgroundColor=[UIColor clearColor];
UIButton *btnCheck=[UIButton buttonWithType:UIButtonTypeCustom];
btnCheck.tag=indexPath.row+300;
if ([arrSelectedRow containsObject:[NSNumber numberWithLong:btnCheck.tag-300]])
{
[btnCheck setImage:[UIImage imageNamed:#"cb_glossy_on#2x.png"] forState:UIControlStateNormal];
}
else
{
[btnCheck setImage:[UIImage imageNamed:#"cb_glossy_off#2x.png"] forState:UIControlStateNormal];
}
btnCheck.frame=CGRectMake(295, cell.center.y-22, 33, 33);
[btnCheck addTarget:self action:#selector(checkClicked:) forControlEvents:UIControlEventTouchUpInside];
cell.accessoryView=btnCheck;
btnCheck=nil;
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger count=[arrSettings count];
CGFloat totalHeight=(16*count)+(count*2);
if (isDesc)
totalHeight+=60;
return totalHeight;
}
Could anyone please suggest me how to display the dynamic data in UITableView based on User Settings for UITableViewCell Labels ?
Change:
if (_cellMain == nil)
to
if (cell == nil)
Add following code in your cellForRowAtIndex method of UITableView
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
I've had the same problem with not smooth tableView scrolling. In my case the reason was in what I forgot to implement tableView method tableView: registerNib: forCellReuseIdentifier: (in that project I used .xib's to create cells).
[self.tableView registerNib:[UINib nibWithNibName:#"YourTableViewCell" bundle:nil] forCellReuseIdentifier:YourCellReuseIdentifier];

UISegmentedControl duplicating in UITableViewCell

In my UITableView Controller I have cells which each contain a UILabel and UISegmentedController. There are about 20 cells in total. The user can select the UISegmentedControl to control whether object is contained in an array or not.
My problem is that as the user scrolls the UISegmentedControl is duplicated and appears as though there are multiple selections for UISegmentedControl. I have a feeling that this is because cells are being reused but unfortunately I don't have a very good understanding of reusing cells.
I have been trying to play around with:
if(cell == nil){}
but I am not sure what should happen there:
Anyway here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"featuresCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *feature = [features objectAtIndex:indexPath.row];
UILabel *titleLabel = (UILabel *)[cell viewWithTag:9999];
titleLabel.text = feature;
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:#"Yes", #"No", nil]];
segmentedControl.frame = CGRectMake(215, 17, 85, 28);
[segmentedControl addTarget:self action:#selector(valueChanged:) forControlEvents: UIControlEventValueChanged];
segmentedControl.tag = indexPath.row;
[cell addSubview:segmentedControl];
if ([selectedFeatures containsObject:feature]) {
segmentedControl.selectedSegmentIndex = 0;
}
else{
segmentedControl.selectedSegmentIndex = 1;
}
return cell;
}
Your help will be greatly appreciated,
Thanks for your time.
cell is never nil so that's not going to help you.
The trick is to mark the cell in some way so as to know whether the segmented control has already been added. The best way is to use the segmented control's tag. Unfortunately you seem to be using the tag for some other purpose, so you'll need to stop doing that:
if (![cell viewWithTag:12345]) {
UISegmentedControl *segmentedControl = // ....;
// ....
segmentedControl.tag = 12345;
[cell.contentView addSubview:segmentedControl];
}
And now, you see, you are guaranteed that there is exactly one segmented control in the cell, and you can find it by calling [cell viewWithTag:12345].
The general rule is that each cell subclass should implement - (void)prepareForReuse to make it ready for configuration in - (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath. I think you can solve your problem by subclassing UITableViewCell, creating each cell with the required UISegmentedControl, and providing a method to configure the segmented control as required.
prepareForReuse should reset the segmented control so that each time you configure your custom cell it is in a known, empty state.
The advantage of this approach is that you are not only reusing the table view cell, but also the segmented control and any other decoration you want the cell to contain. Additionally you have moved the configuration of the cell into the cell object.
Briefly, in the cell subclass init method you create the segmented control and add it as a subview of the contentView.
In the cell subclass configuration method you provide you set the segmented control's segments etc.
In the cell subclass prepareForReuse you remove all those segments and leave the segmented control in a state ready for configuration next time you reuse that cell.
To go even further, start using auto layout to position the segmented control in the cell rather than using a set of hard numbers in a frame. If you get those working on one kind of device that's great but as soon as your cells have different dimensions (in a table view on a different device) things will not look so good.
Try this,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"featuresCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *feature = [features objectAtIndex:indexPath.row];
UILabel *titleLabel = (UILabel *)[cell viewWithTag:9999];
titleLabel.text = feature;
UISegmentedControl *segmentedControl;
if ([cell.contentView viewWithTag:kSegmentTag]) { //kSegmentTag a tag
segmentedControl = (UISegmentedControl *)[cell viewWithTag:kSegmentTag];
} else {
segmentedControl = [[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:#"Yes", #"No", nil]];
segmentedControl.frame = CGRectMake(215, 17, 85, 28);
[segmentedControl addTarget:self action:#selector(valueChanged:) forControlEvents: UIControlEventValueChanged];
segmentedControl.tag = kSegmentTag;
[cell.contentView addSubview:segmentedControl];
}
if ([selectedFeatures containsObject:feature]) {
segmentedControl.selectedSegmentIndex = 0;
}
else{
segmentedControl.selectedSegmentIndex = 1;
}
return cell;
}
and in valueChanged:
- (IBAction)valueChanged:(id)sender {
UISegmentedControl *segmentedControl = (UISegmentedControl *)sender;
CGPoint tablePoint = [segmentedControl convertPoint:segmentedControl.bounds.origin toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:tablePoint];
//here indexpath.row give changed row index
}

Some rows never have UIButtons when UITableView is created

I have a UITableView that is never consistent. This table view has 2 sections.
I have created 2 UIButtons, they both are practically the same image, but one is grey and one is red.
Every row in the UITableView is supposed to have the grey button when the UITableView first loads, and then if a user taps a button then it switches to the red version of the button.
For some reason, about 80% of the time when I load the view controller with this UITableView on my iPhone, the first 2 rows in the first section will not have a button. What's weird is if I tap my finger where the button is supposed to be 2 things happen:
The functionality attached to the button works and NSLogs in the console in xcode.
The red button appears.
So it's like the grey button is there, it's just invisible. This doesn't work because if a user sees 2 rows without a button they are going to think something is broken or that they can't tap on that row.
Also, if I scroll to the very bottom of my UITableView, and then scroll back up again, the invisible grey buttons will magically appear like they were there the whole time.
Here are the first 3 method implementations that are involved in creating my UITableView:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2 ;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(section == 0)
return [self.potentiaFriendsInParseFirstNamesArray count];
if(section == 1)
return [self.potentiaFriendsNotInParseFirstNamesArray count];
else return 0;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if(section == 0)
return #"Friends Using The App";
if(section == 1)
return #"Send to Contact";
else return #"nil";
}
And then here is my cellForRowAtIndexPath method implementation which does most of the work in creating the UITableView and which actually creates the UIButton settings for each row. The if else statement really has 2 sets of nearly identical code, the only difference is one is for section 1 of the table view and the other is for section 2:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"SettingsCell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (indexPath.section == 0) {
NSString *firstNameForTableView = [self.potentiaFriendsInParseFirstNamesArray objectAtIndex:indexPath.row];
PFUser *user = [self.allUsersInParse objectAtIndex:indexPath.row];
UIImage *addUserButtonImage = [UIImage imageNamed:#"SliderThumb-Normal-g"];
UIImage *addUserButtonImageHighlighted = [UIImage imageNamed:#"SliderThumb-Normal"];
UIButton *addUserButton = [[UIButton alloc]init];
addUserButton.frame = CGRectMake(237, -10, 64, 64);
[addUserButton setImage:addUserButtonImage forState:UIControlStateNormal];
[addUserButton setImage:addUserButtonImageHighlighted forState:UIControlStateHighlighted];
[addUserButton setImage:addUserButtonImageHighlighted forState:UIControlStateSelected];
[addUserButton addTarget:self action:#selector(handleTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
addUserButton.tag = indexPath.row;
[cell.textLabel setText:firstNameForTableView];
[cell.detailTextLabel setText:user.username];
[cell.contentView addSubview:addUserButton];
} else {
NSString *firstNameForTableView2 = [self.potentiaFriendsNotInParseFirstNamesArray objectAtIndex:indexPath.row];
NSString *userNameForTableView2 = [self.potentiaFriendsPhoneNumberArray objectAtIndex:indexPath.row];
UIImage *addFriendButtonImage = [UIImage imageNamed:#"SliderThumb-Normal-G"];
UIImage *addFriendButtonImageHighlighted = [UIImage imageNamed:#"SliderThumb-Normal"];
UIButton *addFriendButton = [[UIButton alloc]init];
addFriendButton.frame = CGRectMake(237, -10, 64, 64);
[addFriendButton setImage:addFriendButtonImage forState:UIControlStateNormal];
[addFriendButton setImage:addFriendButtonImageHighlighted forState:UIControlStateHighlighted];
[addFriendButton setImage:addFriendButtonImageHighlighted forState:UIControlStateSelected];
[addFriendButton addTarget:self action:#selector(handleTouchUpInsideForNonUsers:) forControlEvents:UIControlEventTouchUpInside];
addFriendButton.tag = indexPath.row;
[cell.textLabel setText:firstNameForTableView2];
[cell.detailTextLabel setText:userNameForTableView2];
[cell.contentView addSubview:addFriendButton];
}
return cell;
}
I have not included the full method implementations that these 2 statements trigger because they only handle the functionality attached to each button, and most likely have nothing to do with this issue, but I will post them here anyways. These 2 statements can be found in the if else for cellForRowAtIndexPath and handle the touch events for the 2 sections of the table view:
[addFriendButton addTarget:self action:#selector(handleTouchUpInsideForNonUsers:) forControlEvents:UIControlEventTouchUpInside];
[addFriendButton addTarget:self action:#selector(handleTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
I see the pattern of trying to set up a custom UITableViewCell from within tableView:cellForRowAtIndexPath: quite a lot. The trouble is that I believe it to be the wrong place to do it. If you're really only using a built-in UITableViewCell, then it's the right place; for custom cells, it's not.
I'd recommend making a UITableViewCell subclass with a "setup" method that takes an object and uses that object to set up the cell's UI.
For instance, take section 0 from your UITableView. I'd do something like this:
#interface UserTableViewCell : UITableViewCell
// properties to IBOutlet connections for UI setup
- (void)setupWithUser:(PFUser *)user;
#end
#implementation UserTableViewCell
- (void)setupWithUser:(PFUser *)user {
// Set up your UI with properties from 'user'
}
- (IBAction)buttonPressed:(UIButton *)sender {
// Respond to the button press
}
This way, you can set up the cell's layout as well as images for the button in IB, rather than code. This also makes the code a lot easier to read (and re-read 6 months later!).
Also, unless the 2 cells (section 0 and section 1) are really interchangeable, I'd recommend two different subclasses of UITableViewCell to give you greater control, rather than trying to force one to act like the other or vice versa. Then, you simply assign different identifiers and recycle the appropriate type.

Hiding of label in Xcode is not working properly in my tableviewcell of iOS

I am having two labels created manually for displaying it in the tableviewcell named title and detail, code for displaying it are,
dealarray = [[NSMutableArray alloc]initWithObjects:#"1",#"2",#"3",#"4",nil];
detailarray = [[NSMutableArray alloc]initWithObjects:#"oneoneoneoneone oneoneoneoneoneoneoooooooo",#"two",#"three",#"fouronefouronefouronefouronefouronefouronefouron",nil];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
for(UILabel *lbl in [cell.contentView subviews])
{
[lbl removeFromSuperview];
}
cell.accessoryType= UITableViewCellAccessoryNone;
UILabel* title;
title= [[UILabel alloc] initWithFrame:CGRectMake(5,5,300,20)];
[cell.contentView addSubview:title];
[cell.contentView bringSubviewToFront:title];
[title setFont:[UIFont boldSystemFontOfSize:14]];
title.tag = 1001;
title.backgroundColor = [UIColor clearColor];
title.textColor = [UIColor blackColor];
title.text =[dealarray objectAtIndex:indexPath.row];
UILabel* detail;
detail= [[UILabel alloc] initWithFrame:CGRectMake(5,30,300,10)];
[cell.contentView addSubview:detail];
[cell.contentView bringSubviewToFront:detail];
[detail setFont:[UIFont systemFontOfSize:12]];
detail.tag = 1002;
detail.backgroundColor = [UIColor clearColor];
detail.textColor = [UIColor blackColor];
detail.text = [detailarray objectAtIndex:indexPath.row];
return cell
}
No problem in displaying those 2 labels and no problem in hiding all the 'detail' label and displaying the 'title' alone, the problem arises when I try to display the 'detail' label of the resp selective of cells.
Code tried:
// conti of cellforrowatindexpath
detail.numberOfLines = 3;
detail.lineBreakMode = NSLineBreakByWordWrapping;
if (a==-1)// declared 'a' in viewdidload as -1
{
((UILabel*)detail).hidden = YES;
}
else if(a==indexPath.row)
{
((UILabel*)detail).hidden = NO;
}
((UILabel*)detail).hidden = YES;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
a=indexPath.row;
[tableview reloadData];
}
Sorry for posting large amount of codes, it may help any one who is searching for the wholesome data of my doubt.
Whats the mistake am doing, I can't hide the detail label for resp selecting of cells. Can anybody help in this regard?
May I suggest you to use xcode functionnality to design your cell content? (as easy as drag and drop of UILabel on your cell for example) Then you will be able to access them from your code using their respective "tag" id.
A correct way of doing is detail here : http://www.appcoda.com/customize-table-view-cells-for-uitableview/
I think it's a better way than programmatically creating content for your cell, because using xcode interface you will be able to flawlessly define your interface.
Anyway to respond precisely to your question you should try to hide the detail label from "didSelectRowAtIndexPath" :
// Retrieve the corresponding cell
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
// Get the detail label (using its tag) you set it to 1002
UILabel *detail = (UILabel *)[cell viewWithTag:1002];
// Hide it
detail.hidden = true;
Hope this help.
There is an error in your logic. You code as written will always set detail.hidden to YES, the 2 preceding if are ignored, thus this (BTW you don't need the type coercion and extra brackets):
if(a==-1) detail.hidden = YES;
else if (a==indexPath.row) detail.hidden = NO;
else detail.hidden = YES;

Resources