I am populating a TableView dynamically with data called from a server. I have 2 main files, one for the new cell and one for handling the population of the cells within the TableView Now when I assign [cell.button addTarget:self action:#selector(addFriend:) forControlEvents:UIControlEventTouchUpInside]; to my button within the cellForRowAtIndexPath and I put an output to log the action of the clicking of the button, nothing happens.
Here is what I am doing:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
.......
/* Setup button action */
[cell.button addTarget:self action:#selector(addFriend:) forControlEvents:UIControlEventTouchUpInside];
}
- (IBAction)addFriend:(id)sender
{
NSLog(#"Add friend.");
}
Cell Creation:
HomePageTimelineCell *cell = (HomePageTimelineCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[HomePageTimelineCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
Suggestions?
UPDATE:
Here is my cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%d",i);
self.tableView.separatorColor = [UIColor clearColor];// Get rid of speration border color
static NSString *CellIdentifier = #"homecell";
HomePageTimelineCell *cell = (HomePageTimelineCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = [[HomePageTimelineCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[cell initTimelineCell];
cell.backgroundColor = [UIColor clearColor];// Set the background color to the cell
//<!-- Set background color
if (indexPath.row % 2) {
cell.contentView.backgroundColor = [self colorWithHexString:#"77d1af"];
//<!-- Set background and text color for even cells
[cell.button setTitleColor:[self colorWithHexString:#"7ddcb8"] forState:UIControlStateNormal];
cell.button.backgroundColor = [self colorWithHexString:#"666666"];
} else {
cell.contentView.backgroundColor = [self colorWithHexString:#"7ddcb8"];
//<!-- Set background and text color for even cells
[cell.button setTitleColor:[self colorWithHexString:#"7ddcb8"] forState:UIControlStateNormal];
cell.button.backgroundColor = [self colorWithHexString:#"ffffff"];
}
//<!-- if the indexRow row = 0, this is the clients username and address
if(indexPath.row == 0)
{
NSArray *get = [[SSKeychain allAccounts] init];
NSString *username = [get[0] objectForKey:#"acct"];
//<!-- Get keyname of the address and than point to that keyname and get data
NSString *KeyName = [[self.dataGrabed_dictionary allKeys] objectAtIndex: indexPath.row + 4];
//<!-- create uppercase strings
NSString *upperCaseAddress = [[self.dataGrabed_dictionary objectForKey:KeyName] uppercaseString];
NSString *upperCaseUsername = [username uppercaseString];
//<!-- Set associated strings
cell.addressLabel.text = upperCaseAddress;
cell.usernameLabel.text = upperCaseUsername;
}
//<!-- if the indexRow row = 1, this is the 2 cell and will show the most upcoming lawn schedule
else if(indexPath.row == 1)
{ //<!-- create uppercase strings
NSString *upperCaseDay = [[self.dataGrabed_dictionary objectForKey:#"upcoming_day"] uppercaseString];
//<!-- create uppercase strings
NSString *upperCaseDate = [[self.dataGrabed_dictionary objectForKey:#"upcoming_date"] uppercaseString];
cell.contentView.backgroundColor = [self colorWithHexString:#"666666"];
cell.button.backgroundColor = [self colorWithHexString:#"7ddcb8"];
cell.button.tag = indexPath.row;
[cell.button setTitle:#"change" forState:UIControlStateNormal];
[cell.button setTitleColor:[self colorWithHexString:#"666666"] forState:UIControlStateNormal];
/* Setup button action */
[cell.button addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
cell.dayLabel.text = upperCaseDay;//<!-- Set the day
cell.dateLabel.text = upperCaseDate;//<!-- Set the Date
[cell.contentView addSubview:cell.button];
[cell.contentView addSubview:cell.nextLabel];
[cell.contentView addSubview:cell.dayLabel];
[cell.contentView addSubview:cell.dateLabel];
}
else //<!-- Normal cell population
{
//<!-- Re edit labels positioning
cell.dayLabel.frame = CGRectMake(9, 10, 200, 45);
cell.dateLabel.frame = CGRectMake(9, 35, 300, 45);
//<!-- Setup data called from server
NSDictionary *innerClientData =[self.dataGrabed_dictionary objectForKey:#"scheduled_times"][i];
NSString *innerClientDay =[self.dataGrabed_dictionary objectForKey:#"scheduled_times_day"][i];
NSString *innerClientDate =[self.dataGrabed_dictionary objectForKey:#"scheduled_times_date"][i];
//<!-- create uppercase strings
NSString *upperCaseDay = [innerClientDay uppercaseString];
//<!-- create uppercase strings
NSString *upperCaseDate = [ innerClientDate uppercaseString];
//<!-- Check to see if client paid
if([[innerClientData objectForKey:#"client_paid"] isEqual: #"0"])
{
NSString *amount = [innerClientData objectForKey:#"client_price"];
NSString *pay = #"pay $";
NSString * combined = [pay stringByAppendingString:amount];
[cell.button setTitle:combined forState:UIControlStateNormal];
}
else if([[innerClientData objectForKey:#"client_paid"] isEqual: #"1"])
{
[cell.button setTitle:#"PAID" forState:UIControlStateNormal];
}
//[cell.button setTitleColor:[self colorWithHexString:#"666666"] forState:UIControlStateNormal];
cell.button.tag = indexPath.row;
/* Setup button action */
[cell.button addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
cell.dayLabel.text = upperCaseDay;//<!-- Set the day
cell.dateLabel.text = upperCaseDate;//<!-- Set the Date
[cell.contentView addSubview:cell.button];
[cell.contentView addSubview:cell.dayLabel];
[cell.contentView addSubview:cell.dateLabel];
i++;
}
return cell;
}
Here is my HomePageTimelineCell cell creator:
#import "HomePageTimelineCell.h"
#import "HomePage.h"
#implementation HomePageTimelineCell
#synthesize cellContentView;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
cellContentView = [[UIView alloc] initWithFrame:CGRectMake(0, 5, 300, 85)];
cellContentView.backgroundColor = [UIColor clearColor];
_usernameLabel = [[UILabel alloc] initWithFrame:CGRectMake(9, 10, 300, 45)];
_usernameLabel.font = [UIFont fontWithName:#"AppleSDGothicNeo-SemiBold" size:30.0];
_usernameLabel.textColor = [UIColor whiteColor];
_addressLabel = [[UILabel alloc] initWithFrame:CGRectMake(9, 40, 300, 45)];
_addressLabel.font = [UIFont fontWithName:#"AppleSDGothicNeo-Light" size:20.0];
_addressLabel.textColor = [UIColor whiteColor];
_addressLabel.numberOfLines = 1;
_addressLabel.lineBreakMode = NSLineBreakByTruncatingTail;
_nextLabel = [[UILabel alloc] initWithFrame:CGRectMake(9, 0, 100, 45)];
_nextLabel.font = [UIFont fontWithName:#"AppleSDGothicNeo-Thin" size:25.0];
_nextLabel.textColor = [UIColor whiteColor];
_nextLabel.text = #"NEXT";
_dayLabel = [[UILabel alloc] initWithFrame:CGRectMake(9, 25, 200, 45)];
_dayLabel.font = [UIFont fontWithName:#"AppleSDGothicNeo-SemiBold" size:35.0];
_dayLabel.textColor = [UIColor whiteColor];
_dateLabel = [[UILabel alloc] initWithFrame:CGRectMake(9, 50, 300, 45)];
_dateLabel.font = [UIFont fontWithName:#"AppleSDGothicNeo-Thin" size:25.0];
_dateLabel.textColor = [UIColor whiteColor];
// IMPACT BUTTON STYLES
_button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
_button.layer.cornerRadius = 0.0f;
_button.frame = CGRectMake(220, 20, 80, 45);
/* ADD ALL THE CONTENT */
[self addSubview:cellContentView];
[cellContentView addSubview:_usernameLabel];
[cellContentView addSubview:_addressLabel];
}
return self;
}
- (void) initTimelineCell
{
cellContentView.layer.cornerRadius = 2;
cellContentView.layer.masksToBounds = NO;
configured = YES;
}
- (bool) configured
{
return configured;
}
#end
Premise that you should provide more code to have a clear idea of what is happening,
this is not the best approach.
At least I hope you are adding the target just if the cell is nil and you are init that and not more and more time :)
But anyway, the correct approach in functionality and design, is to implement the button action in the cell subclass, and return back by a delegate the cell where the button touched was.
I explained the various approaches here, the last one is this.
Enjoy clean code and good design ;)
Related
I am facing an issue in custom cell, while scrolling up and down the values in the cell changing. I have added 2 buttons in the last section. Please check the below code. Any help, much appreciated. Thanks a ton.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cell";
DrinkCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[DrinkCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
if (indexPath.section == [tableView numberOfSections] - 1)
{
cell.tileImage.hidden = YES;
cell.pizzaTopins.hidden = YES;
// cell.accessoryType = UITableViewCellAccessoryNone;
if (indexPath.row == 0) {
cell.separatorInset = UIEdgeInsetsMake(0.f, 0.f, 0.f, cell.bounds.size.width);
UILabel *calorieLabel = [[UILabel alloc]initWithFrame:CGRectMake(5, cell.contentView.frame.size.height/2-30/2, self.tableView.frame.size.width, 30)];
calorieLabel.text = #"1000 Calories | 700 grams of fat";
cell.backgroundColor = backgroundColorApp;
[cell addSubview:calorieLabel];
}
else if (indexPath.row == 1) {
cell.backgroundColor = backgroundColorApp;
NSLog(#"cell width : %f",cell.contentView.frame.size.width);
UIView *quantityView = [[UIView alloc]init];
quantityView.frame = CGRectMake(25 ,cell.contentView.frame.size.height/2-50/2, cell.contentView.frame.size.width-55, 50);
quantityView.backgroundColor = [UIColor whiteColor];
quantityView.clipsToBounds = YES;
quantityView.userInteractionEnabled = YES;
quantityView.layer.cornerRadius = 10.0f;
UIButton *decreaseButton = [[UIButton alloc]initWithFrame:CGRectMake(10, quantityView.frame.size.height/2-35/2, 35, 35)];
[decreaseButton setTitle:#"-" forState:UIControlStateNormal];
[quantityView addSubview:decreaseButton];
[decreaseButton addTarget:self action:#selector(decreaseQuantity:) forControlEvents:UIControlEventTouchUpInside];
[decreaseButton setTitleColor:quantityButtonColor forState:UIControlStateNormal];
[decreaseButton setTintColor:[UIColor greenColor]];
decreaseButton.clipsToBounds = YES;
decreaseButton.layer.cornerRadius = 17.5f;
decreaseButton.layer.borderColor = quantityButtonColor.CGColor;
decreaseButton.layer.borderWidth = 1.5f;
int i =0;
quantityLabel = [[UILabel alloc]initWithFrame:CGRectMake(quantityView.frame.size.width/2-30/2, quantityView.frame.size.height/2-30/2, 30, 30)];
quantityLabel.text = [NSString stringWithFormat:#"%d",i];
[quantityLabel setFont:[UIFont boldSystemFontOfSize:18]];
quantityLabel.textColor = quantityButtonColor;
[quantityView addSubview:quantityLabel];
UIButton *increaseButton = [[UIButton alloc]initWithFrame:CGRectMake(quantityView.frame.size.width-45, quantityView.frame.size.height/2-35/2, 35, 35)];
[increaseButton setTitle:#"+" forState:UIControlStateNormal];
[increaseButton addTarget:self action:#selector(increaseQuantity:) forControlEvents:UIControlEventTouchUpInside];
[quantityView addSubview:increaseButton];
increaseButton.clipsToBounds = YES;
[increaseButton setTitleColor:quantityButtonColor forState:UIControlStateNormal];
increaseButton.layer.cornerRadius = 17.5f;
increaseButton.layer.borderColor = quantityButtonColor.CGColor;
increaseButton.layer.borderWidth = 1.5f;
[cell addSubview:quantityView];
[quantityView addSubview:decreaseButton];
[quantityView addSubview:increaseButton];
}
else if (indexPath.row == 2) {
addTocartButton = [[UIButton alloc]initWithFrame:CGRectMake(25, cell.contentView.frame.size.height/2 - 50/2, cell.contentView.frame.size.width-55, 50)];
[addTocartButton setTitle:#"Add to Cart" forState:UIControlStateNormal];
[addTocartButton addTarget:self action:#selector(addToCartOnCreatePizza:) forControlEvents:UIControlEventTouchUpInside];
addTocartButton.backgroundColor = [UIColor colorWithRed:190.0f/255.0f green:19.0f/255.0f blue:31.0f/255.0f alpha:1.0];
// [cell.contentView addSubview:addTocartButton];
[cell.contentView insertSubview:addTocartButton atIndex:0];
addTocartButton.clipsToBounds = YES;
addTocartButton.layer.cornerRadius =10.0f;
}
}
cell.pizzaTopins.textColor = [UIColor colorWithRed:190.0f/255.0f green:19.0f/255.0f blue:31.0f/255.0f alpha:1.0];
cell.pizzaTopins.text = [dataArray objectAtIndex:indexPath.row];
cell.tileImage.image = [UIImage imageNamed:#"profile44.png"];
// cell.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
return cell;
}
dequeueReusableCellWithIdentifier will "reuse" previously created cells so you have to make sure to re-initialize all manually added/modified attributes including any buttons you added programatically.
Screen shots would help us properly diagnose the issue but your code is vulnerable to lingering attributes of reused cells so I would suggest starting with that.
BTW you would probably end up with simpler code if you defined multiple cell prototypes in IB and varied the cellIdentifier based on the indexPath row.
I'm implementing a UITableView with text-views as the content view of my cells.
The data that the user enters is saved in a settings dictionary when the user hits the return key:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == _textFieldOne){
[settingsDictionary setObject: _textFieldOne.text forKey:#"EntryOneText"];
[settingsDictionary stringValueForKey:#"textFieldOneValue"];
[self postNotificationSettingsUpdate:settingsDictionary];
didTestPostNotificationSettings = YES;
}
These saved values should be displayed in the text-field when the user returns back to the screen, which I've done using the code below:
//Set the value in the text fields from the settings dictionary
NSString *textFieldOneText = [self.settingsDictionary stringValueForKey:#"RedZoneCarsPerManHrMin"];
_textFieldOne.text = textFieldOneValue;
So far, everything seems to work as expected: text input is saved, and shown in the text-field when the user returns to screen. However, if the row of the TableView that holds the text-field is select (not the text-field itself), the text-field displays the behavior shown below:
It appears as if the text-field is showing both the newly inputted entry, as well as the entry that was last saved.
EDIT I'ved added more of my cellForRowAtIndexPath method below:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForSubscribedRedZoneAlertRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"RedZoneAlertCell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
}
cell.backgroundColor = [UIColor colorWithRed:0.922 green:0.937 blue:0.949 alpha:1];
UISwitch *cellSwitch = nil;
NSNumber *position = enabledRedZoneAlertRows[indexPath.row];
switch (position.integerValue) {
case CarPerManHourRow: {
cell.textLabel.text = NSLocalizedString(#"Label", #"Label Row");
cellSwitch = [[UISwitch alloc] init];
cellSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:SwitchKey];
cellSwitch.tag = SwitchTag;
[cellSwitch addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = cellSwitch;
if ([[self.settingsDictionary valueForKey:#"RedZoneCarsPerManHrOnOff"]isEqual: #"1"]){
[cellSwitch setOn:YES];
}
break;
}
case TextFieldRow: {
static NSString *CellIdentifier = #"ConfigCell";
cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
[cell.contentView addSubview:_textFieldOne];
[cell.contentView addSubview:_textFieldTwo];
[cell.contentView addSubview:_spacingLabel];
}
cell.backgroundColor = [UIColor colorWithRed:0.922 green:0.937 blue:0.949 alpha:1];
_textFieldOne = [[UITextField alloc]initWithFrame:CGRectMake(25, 0, 50, 30)];
_textFieldTwo = [[UITextField alloc]initWithFrame:CGRectMake(100, 0, 50, 30)];
_textFieldOne.delegate = self;
_textFieldTwo.delegate = self;
_textFieldOne.placeholder = #"Auto";
_textFieldTwo.placeholder = #"Auto";
[_textFieldOne setTextAlignment:NSTextAlignmentCenter];
[_textFieldTwo setTextAlignment:NSTextAlignmentCenter];
//Set the value in the text fields from the settings dictionary
NSString *textFieldOneText = [self.settingsDictionary stringValueForKey:#"RedZoneCarsPerManHrMin"];
NSString *textFieldTwoText = [self.settingsDictionary stringValueForKey:#"RedZoneCarsPerManHrMax"];
NSString *carsPerManHrMax = [self.settingsDictionary stringValueForKey:#"RedZoneCarsPerManHrMax"];
NSString *carsPerManHrMax = [self.settingsDictionary stringValueForKey:#"RedZoneCarsPerManHrMax"];
_textFieldOne.text = textFieldOneValue;
_textFieldTwo.text = textFieldTwoValue
_textFieldOne.backgroundColor = [UIColor whiteColor];
_textFieldTwo.backgroundColor = [UIColor whiteColor];
_textFieldOne.tintColor = [UIColor blackColor];
_textFieldTwo.tintColor = [UIColor blackColor];
[_textFieldOne.layer setCornerRadius:7.0f];
[_textFieldTwo.layer setCornerRadius:7.0f];
[_textFieldOne setKeyboardType:UIKeyboardTypeNumbersAndPunctuation];
[_textFieldTwo setKeyboardType:UIKeyboardTypeNumbersAndPunctuation];
_textFieldOne.returnKeyType = UIReturnKeyNext;
_textFieldTwo.returnKeyType = UIReturnKeyDone;
_spacingLabel = [[UILabel alloc] initWithFrame:CGRectMake(70, 0, 35, 30)];
_spacingLabel.text = #"–";
_spacingLabel.textColor = [UIColor colorWithRed:0.658 green:0.658 blue:0.658 alpha:1];
[_spacingLabel setTextAlignment:NSTextAlignmentCenter];
_spacingLabel.backgroundColor = [UIColor clearColor];
//[cell.contentView addSubview:_textFieldOne];
//[cell.contentView addSubview:_textFieldTwo];
//[cell.contentView addSubview:_spacingLabel];
break;
}
return cell;
}
EDIT TWO
Below is my attempt at fixing my issue based on jherran's answer. However, I am still experiencing the same problem.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForSubscribedRedZoneAlertRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"RedZoneAlertCell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
}
cell.backgroundColor = [UIColor colorWithRed:0.922 green:0.937 blue:0.949 alpha:1];
UISwitch *cellSwitch = nil;
NSNumber *position = enabledRedZoneAlertRows[indexPath.row];
switch (position.integerValue) {
case CarPerManHourRow: {
cell.textLabel.text = NSLocalizedString(#"Label", #"Label Row");
cellSwitch = [[UISwitch alloc] init];
cellSwitch.on = [[NSUserDefaults standardUserDefaults] boolForKey:SWSettingCarsPerManHour];
cellSwitch.tag = SaveCarsPerManHourTag;
[cellSwitch addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = cellSwitch;
if ([[self.settingsDictionary valueForKey:#"RedZoneCarsPerManHrOnOff"]isEqual: #"1"]){
[cellSwitch setOn:YES];
}
break;
}
case CarsPerManHourConfigRow: {
static NSString *CellIdentifier = #"ConfigCell";
cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
cell.backgroundColor = [UIColor colorWithRed:0.922 green:0.937 blue:0.949 alpha:1];
_carsPerManHourMinTextField = [[UITextField alloc]initWithFrame:CGRectMake(25, 0, 50, 30)];
_carsPerManHourMaxTextField = [[UITextField alloc]initWithFrame:CGRectMake(100, 0, 50, 30)];
_textFieldOne.delegate = self;
_textFieldTwo.delegate = self;
_textFieldOne.placeholder = #"Auto";
_textFieldTwo.placeholder = #"Auto";
[_textFieldOne setTextAlignment:NSTextAlignmentCenter];
[_textFieldTwo setTextAlignment:NSTextAlignmentCenter];
_textFieldOne.backgroundColor = [UIColor whiteColor];
_textFieldTwo.backgroundColor = [UIColor whiteColor];
_textFieldOne.tintColor = [UIColor blackColor];
_textFieldTwo.tintColor = [UIColor blackColor];
[_textFieldOne.layer setCornerRadius:7.0f];
[_textFieldTwo.layer setCornerRadius:7.0f];
[_textFieldOne setKeyboardType:UIKeyboardTypeNumbersAndPunctuation];
[_carsPerManHourMaxTextField setKeyboardType:UIKeyboardTypeNumbersAndPunctuation];
_textFieldOne.returnKeyType = UIReturnKeyNext;
_textFieldTwo.returnKeyType = UIReturnKeyDone;
_spacingLabel = [[UILabel alloc] initWithFrame:CGRectMake(70, 0, 35, 30)];
_spacingLabel.text = #"–";
_spacingLabel.textColor = [UIColor colorWithRed:0.658 green:0.658 blue:0.658 alpha:1];
[_spacingLabel setTextAlignment:NSTextAlignmentCenter];
_spacingLabel.backgroundColor = [UIColor clearColor];
NSLog(#"%#", _textFieldOne.text);
NSLog(#"%#",_carsPerManHourMaxTextField.text);
[cell.contentView addSubview: _textFieldOne];
[cell.contentView addSubview: _textFieldTwo];
[cell.contentView addSubview:_spacingLabel];
cell.tag = 1;
}
else {
_textFieldOne = (UITextField *)[cell.contentView viewWithTag:1];
_textFieldTwo = (UITextField *)[cell.contentView viewWithTag:1];
_spacingLabel = (UILabel *)[cell.contentView viewWithTag:1];
}
NSString * _textFieldOne = [self.settingsDictionary stringValueForKey:#"RedZoneCarsPerManHrMin"];
NSString *carsPerManHrMax = [self.settingsDictionary stringValueForKey:#"RedZoneCarsPerManHrMax"];
_textFieldOne.text = carsPerManHrMin;
_textFieldTwo.text = carsPerManHrMax;
How do I modify my code so that this behavior does not occur?
Check your cellForRowAtIndexPath, as cells are reused, you are probably not loading the cell property.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
/*
* This is an important bit, it asks the table view if it has any available cells
* already created which it is not using (if they are offscreen), so that it can
* reuse them (saving the time of alloc/init/load from xib a new cell ).
* The identifier is there to differentiate between different types of cells
* (you can display different types of cells in the same table view)
*/
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyIdentifier"];
/*
* If the cell is nil it means no cell was available for reuse and that we should
* create a new one.
*/
UILabel *label;
if (cell == nil) {
/*
* Actually create a new cell (with an identifier so that it can be dequeued).
*/
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MyIdentifier"] autorelease];
label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 30)];
cell.tag = 1;
[cell.contentView addSubview:label];
} else {
label = (UILabel *)[cell.contentView viewWithTag:1];
}
/*
* Now that we have a cell we can configure it to display the data corresponding to
* this row/section
*/
label.text = #"whatever";
}
EDIT: When your cell exits and it's reused, you are adding a view ([cell.contentView addSubview:_textFieldOne]) each time the cell is reused.
Ok, it is as I suspected. Every time the cell is taken out out the reuse queue, you create a new instance of textfield and add it to the content view. So basically the content view is piling up with new textfields.
What you should do is
1) to have a custom cell and make the cell the sole class responsible for its internals
2) expose only a configuration method to pass a raw text to cell
3) call that configuration method when thr cell is reused.
4) keep a reference to the textfield inside the custom cell to be able to update the text value any time incl. when it is recycled in cellforrowatindexpath
I have a UITableView that has its delegate and dataSource properties set correctly, however its content isn't showing.
MY Code
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
BOOL notInputNotes;
UIColor *normalBlue = [[UIColor alloc]initWithRed:0.1 green:0.65 blue:1.0 alpha:0.8];
HomeWork *hw = [hwArray objectAtIndex:indexPath.row];
NSString *dateDueAsText = [dateFormat stringFromDate:hw.dateDue];
CGFloat xForDate;
if (dateDueAsText.length < 16 || dateDueAsText.length == 16) {
xForDate = 215;
}
else{
xForDate = 214;
}
hw.indexPath = indexPath;
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
for (UIView *view in cell.subviews) {
[view removeFromSuperview];
}
if (!isEditing) {
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[cell setEditing:NO];
}
else{
cell.selectionStyle = UITableViewCellSelectionStyleDefault;
[cell setEditing:YES];
}
UILabel *subject = [[UILabel alloc]initWithFrame:CGRectMake(70, 5, 150, 45)];
if(![hw.subject isEqualToString:#""])
{
subject.text = hw.subject;
notInputNotes = NO;
}
else{
subject.text = hw.notes;
subject.frame = CGRectMake(70, 20, 150, 45);
notInputNotes = YES;
}
[subject setFont:[UIFont systemFontOfSize:20]];
[subject setTextColor:normalBlue];
subject.adjustsFontSizeToFitWidth = YES;
subject.backgroundColor = [UIColor blueColor];//test
[cell addSubview:subject];
if(!notInputNotes){
UILabel *notes = [[UILabel alloc]initWithFrame:CGRectMake(70, 40, 300, 30)];
notes.text = hw.notes;
[notes setFont:[UIFont systemFontOfSize:12]];
notes.adjustsFontSizeToFitWidth = YES;
[notes setTextColor:[UIColor colorWithRed:0.2 green:0.3 blue:1.0 alpha:1.0]];
[cell addSubview:notes];
}
UILabel *importancy = [[UILabel alloc]initWithFrame:CGRectMake(300, 45, 200, 30)];
importancy.text = hw.importancy;
[importancy setFont:[UIFont systemFontOfSize:12]];
[importancy setTextColor:[UIColor redColor]];
importancy.adjustsFontSizeToFitWidth = YES;
[cell addSubview:importancy];
UILabel *dateDue = [[UILabel alloc]initWithFrame:CGRectMake(xForDate, 10, 200, 30)];
dateDue.text = [NSString stringWithFormat:#"%#",dateDueAsText];
[dateDue setFont:[UIFont systemFontOfSize:13]];
dateDue.textColor = normalBlue;
dateDue.adjustsFontSizeToFitWidth = YES;
[cell addSubview:dateDue];
hw.doneButton = [[UIButton alloc]initWithFrame:CGRectMake(20, 25, 40, 40)];
if(!hw.done){
[hw.doneButton setImage:[UIImage imageNamed:#"unchecked.png"] forState:UIControlStateNormal];
}
else{
[hw.doneButton setImage:[UIImage imageNamed:#"checked.png"] forState:UIControlStateNormal];
}
[hw.doneButton addTarget:hw action:#selector(done:) forControlEvents:UIControlEventTouchUpInside];
NSDateComponents *dayComponent = [[NSDateComponents alloc] init];
dayComponent.day = -1;
NSCalendar *theCalendar = [NSCalendar currentCalendar];
NSDate *nowMinus1 = [theCalendar dateByAddingComponents:dayComponent toDate:[NSDate date] options:0];
NSComparisonResult result;
result = [nowMinus1 compare:hw.dateDue];
if(result==NSOrderedDescending && !(hw.done)){
cell.backgroundColor = [UIColor colorWithWhite:0.86 alpha:0.6];
NSLog(#"%# is earlier than %#",dateDueAsText,[dateFormat stringFromDate:nowMinus1]);
[hw.doneButton setImage:[UIImage imageNamed:#"lighter-gray_unckecked.jpg"] forState:UIControlStateNormal];
hw.late = YES;
}
else{
cell.backgroundColor = [UIColor whiteColor];
hw.late = NO;
}
[cell addSubview:hw.doneButton];
return cell;
}
Does somebody know what's wrong there? Thanks in advance.
Note
the cell's background color appears different if you set it, so the cells are there and re correctly made the problem is really with the views
I wouldn't say it is a really good practice to remove all subviews of a UITableViewCell and add your own subviews after. It would be better to subclass UITableViewCell.
That being said, you can try this instead, it will display your content.
for (UIView *view in cell.contentView.subviews) {
[view removeFromSuperview];
}
But your problem definitely comes from you wanting to remove the subviews. If the first problem is cell overlapping try implementing
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return customHeight;
}
I have two UIButtons and some labels inside a table view cell. I have 2 sections, the first section contains one table view cell and inside of that cell there are two UIButtons that call on an api to fetch new data for the cells in section 2. In a certain if case, a label is created because the string is very long so I have to create a new frame for the cell.
The problem that I am currently having is that the button text also gets update with new information and sometimes the string is short or sometimes the string is long, so I have to remove the button and a add a new button with a new frame to fit the new string. But if the past button string was shorter than the new one, the button still appears in the background. I tried removing it from the superview and also checking that it has removed from the superview (check that it is null once I remove it) and it is, but it still appears on the screen. The same thing happens with the UILabels as well. I also tried to removing them from super view with a tag (viewWithTag:123). Anyone have any pointers, ideas, suggestions, anything really, that could help me figure/fix this out?
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
UIView *selectedBackgroundView = [[UIView alloc] initWithFrame:CGRectZero];
selectedBackgroundView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.1];
cell.selectedBackgroundView = selectedBackgroundView;
if(cell==nil) { NSLog(#"Cell is still nil");}
}
cell.textLabel.text = nil;
cell.accessoryView = nil;
cell.detailTextLabel.text = nil;
cell.userInteractionEnabled = YES;
if(indexPath.section == 0)
{
dosageButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
amountButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[dosageButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[dosageButton setContentEdgeInsets:UIEdgeInsetsMake(0, 15, 0, 0)];
[amountButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft];
[amountButton setContentEdgeInsets:UIEdgeInsetsMake(0, 15.5, 0, 0)];
if(strengths.count == 0) { [dosageButton setTitle:#"Dosage" forState:UIControlStateNormal];}
else
{
[dosageButton setTitle:selectedStrength forState:UIControlStateNormal];
CGSize stringsize = [selectedStrength sizeWithFont:[UIFont systemFontOfSize:14]];
[dosageButton setFrame:CGRectMake(5, 27.5, stringsize.width + 30, 30)];
}
if(quantity.count == 0) { [amountButton setTitle:#"Amount" forState:UIControlStateNormal];}
else
{
int value = [selectedQuantity intValue];
if (value == 1)
{
NSString *amountAndFormat = [NSString stringWithFormat:#"%# %#", selectedQuantity, selectedFormat];
[amountButton setTitle:amountAndFormat forState:UIControlStateNormal];
CGSize stringsize = [selectedStrength sizeWithFont:[UIFont systemFontOfSize:14]];
CGSize amountSize = [amountAndFormat sizeWithFont:[UIFont systemFontOfSize:14]];
if(amountSize.width+stringsize.width > 250)
{
dosageButton.frame = CGRectMake(5, 27.5, 130, 30);
amountButton.frame = CGRectMake(140, 27.5, 160, 30);
}
else
{
[amountButton setFrame:CGRectMake(stringsize.width + 40, 27.5, amountSize.width + (amountSize.height * 2.1), 30)];
}
}
else
{
NSString *amountAndFormat = [NSString stringWithFormat:#"%# %#", selectedQuantity, selectedFormatPlural];
[amountButton setTitle:amountAndFormat forState:UIControlStateNormal];
CGSize stringsize = [selectedStrength sizeWithFont:[UIFont systemFontOfSize:14]];
CGSize amountSize = [amountAndFormat sizeWithFont:[UIFont systemFontOfSize:14]];
if(amountSize.width + stringsize.width> 250)
{
dosageButton.frame = CGRectMake(5, 27.5, 130, 30);
amountButton.frame = CGRectMake(140, 27.5, 160, 30);
}
else
{
[amountButton setFrame:CGRectMake(stringsize.width + 40, 27.5, amountSize.width + (amountSize.height * 2.1), 30)];
}
}
}
[dosageButton addTarget:self action:#selector(showDosages:) forControlEvents:UIControlEventTouchUpInside];
[amountButton addTarget:self action:#selector(showAmount:) forControlEvents:UIControlEventTouchUpInside];
//[cell.contentView addSubview:dosageButton];
//[cell.contentView addSubview:amountButton];
//adding it to view instead of cell because of userInteraction.
//if I add it to cell.contentView and userInteractionEnabled = NO
//then the user can't press the button
//but if the it is enabled then they can click the cell and looks tacky!
[self.view addSubview:dosageButton];
[self.view addSubview:amountButton];
cell.userInteractionEnabled = NO;
}
if(indexPath.section == 1)
{
if(localName.count == 0)
{
//Nothing
}
else
{
CGRect longStringFrame = CGRectMake(12, 4, 250, 120);
//UILabel *longStringLabel = [[UILabel alloc] initWithFrame:longStringFrame];
UILabel *longStringLabel = [[UILabel alloc] initWithFrame:longStringFrame];
longStringLabel.backgroundColor = [UIColor clearColor];
longStringLabel.font = [UIFont systemFontOfSize:12];
longStringLabel.text = [NSString stringWithFormat:#"Something super duper long. Some really really long string that has a lot of information and cannot fit in one line so I have to use numberOfLines = 0 and NSLineBreakByWordWrapping. This string is really really really long.]];
longStringLabel.textColor = [UIColor blackColor];
longStringLabel.numberOfLines = 0;
longStringLabel.lineBreakMode = NSLineBreakByWordWrapping;
cell.textLabel.text = #"";
longStringLabel.tag = 123;
[cell.contentView addSubview:longStringLabel];
}
}
}
- (void) showDosages:(UIButton *)sender
{
[dosageButton removeFromSuperview];
[amountButton removeFromSuperview];
[[cell.contentView viewWithTag:123] removeFromSuperview];
NSLog(#"%#",[dosageButton superview]);
NSLog(#"%#",[amountButton superview]);
//Also tried it this way as well. Didn't work
//[dosageButton performSelectorOnMainThread:#selector(removeFromSuperview) withObject:nil waitUntilDone:NO];
//[amountButton performSelectorOnMainThread:#selector(removeFromSuperview) withObject:nil waitUntilDone:NO];
dispatch_async(someDispatch, ^{ NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString: [NSString stringWithFormat: #"http://somewebsite.com"]]]; [self performSelectorOnMainThread:#selector(fetchData:) withObject:data waitUntilDone:YES]; });
}
showAmount is similar to showDosages
I would suggest you to create a custom cell put all the labels & buttons you want, give an iboutles so that you can easily manage things.
Custom cell tutorial
http://mobile.tutsplus.com/tutorials/iphone/customizing-uitableview-cell/
Once you made your cell you can set the height of cell according to your string. Your buttons will automatically adjusted when your cell size is increased or decreased
Here is the simple example of multiple cell identifier hope it might help
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier1 = #"Cell1";
static NSString *CellIdentifier2 = #"Cell2";
if(flag == 0) {
MainArticleTableViewCell *cell = (MainArticleTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
if (cell == nil) {
cell = [[[MainArticleTableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier1] autorelease];
}
cell.textLabel.text= #"Cell1";
return cell;
}
else {
NewsTableViewCell *cell = (NewsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
if (cell == nil) {
cell = [[[NewsTableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier2 orientation:currentOrientation] autorelease];
}
cell.textLabel.text= #"Cell1";
return cell;
}
return nil;
}
I create a tableview has button, this button has been changed image ass different condition. The first load tableview, these buttons set image correct but after condition change, it set image incorrect. Example : If [Selling = 0] , set image "Market.png", else [Selling =2], set image "MarketSelect.png". When value of Selling array changing, i used [_tableview reloadData] but it still not change image. I debug, i see MarketButton is 0x0000. The first load, MarketButton works correct but second load, it is 0x0000. Please give me advice to solve this problem. I tried 2 days but it can not works. thanks much
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CustomCell *cell = (CustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (nil == cell) {
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.button.tag = indexPath.row;
UIButton *market = [UIButton buttonWithType:UIButtonTypeCustom];
[market setFrame:CGRectMake(200, 6, 30, 30)];
market.tag = 4000;
[market addTarget:self action:#selector(marketPressedAction:) forControlEvents:UIControlEventTouchDown];
[cell.contentView addSubview:market];
UILabel *pricelabel = [[UILabel alloc] initWithFrame:CGRectMake(80, 0, 80, 30)];
pricelabel.backgroundColor = [UIColor clearColor];
pricelabel.font = [UIFont fontWithName:#"Helvetica" size:16];
pricelabel.font = [UIFont boldSystemFontOfSize:16];
pricelabel.textColor = [UIColor darkGrayColor];
pricelabel.tag = 3000;
//pricelabel.hidden = YES;
pricelabel.textAlignment = NSTextAlignmentRight;
[cell.contentView addSubview: pricelabel];
[pricelabel release];
}
UIButton *marketButton = (UIButton*)[cell.contentView viewWithTag:4000];
[marketButton setTag:indexPath.row];
if([sellingArray count]>0)
{
NSLog(#"sellingArray %#",sellingArray);
if([[sellingArray objectAtIndex:indexPath.row] isEqualToString:#"0"]) // nothing
{
[marketButton setSelected:NO];
[marketButton setImage:[UIImage imageNamed:#"Marketplace.png"] forState:UIControlStateNormal];
marketButton.enabled = YES;
}
else if([[sellingArray objectAtIndex:indexPath.row] isEqualToString:#"2"]) // marketplace
{
[marketButton setSelected:YES];
[marketButton setImage:[UIImage imageNamed:#"MarketplaceSelect.png"] forState:UIControlStateNormal];
marketButton.enabled = YES;
}
}
}
UILabel *pricelbl = (UILabel*)[cell.contentView viewWithTag:3000];
pricelbl.text =[NSString stringWithFormat:#"$%#",[priceNewArray objectAtIndex:indexPath.row]];
if ([sellingArray count]>0) {
if([[sellingArray objectAtIndex:indexPath.row] isEqualToString:#"2"]){
pricelbl.hidden = NO;
}
else if([[sellingArray objectAtIndex:indexPath.row] isEqualToString:#"0"]){
pricelbl.hidden = YES;
}
}
return cell;
}
marketpressAction :
- (void)marketPressedAction:(id)sender
{
buttonPressed = (UIButton *)sender;
buttontag = buttonPressed.tag;
NSLog(#"Market button click at row %d",buttontag);
}